P1074 靶形数独

这里写图片描述

sudoku1
7 0 0 9 0 0 0 0 1
1 0 0 0 0 5 9 0 0
0 0 0 2 0 0 0 8 0
0 0 5 0 2 0 0 0 3
0 0 0 0 0 0 6 4 8
4 1 3 0 0 0 0 0 0
0 0 7 0 0 2 0 9 0
2 0 1 0 6 0 8 0 4
0 8 0 5 0 4 0 1 2

sudoku2
0 0 0 7 0 2 4 5 3
9 0 0 0 0 8 0 0 0
7 4 0 0 0 5 0 1 0
1 9 5 0 8 0 0 0 0
0 7 0 0 0 0 0 2 5
0 3 0 5 7 9 1 0 8
0 0 0 6 0 1 0 0 0
0 6 0 9 0 0 0 0 1
0 0 0 0 0 0 0 0 6

sudoku1
2829

sudoku2
2852

以后学习位运算的做法及dancing links

#include<iostream>
#include<cstdio>
using namespace std;
int x,t=81,ans,flag;
int a[10][10],row[10][10],col[10][10],block[10][10];
int v[10][10]=
{
0,0,0,0,0, 0,0,0,0,0,
0,6,6,6,6, 6,6,6,6,6,
0,6,7,7,7, 7,7,7,7,6,
0,6,7,8,8, 8,8,8,7,6,
0,6,7,8,9, 9,9,8,7,6,
0,6,7,8,9,10,9,8,7,6,
0,6,7,8,9, 9,9,8,7,6,
0,6,7,8,8, 8,8,8,7,6,
0,6,7,7,7, 7,7,7,7,6,
0,6,6,6,6, 6,6,6,6,6
};
int ju[10][10]={
0,0,0,0,0,0,0,0,0,0,
0,1,1,1,2,2,2,3,3,3,
0,1,1,1,2,2,2,3,3,3,
0,1,1,1,2,2,2,3,3,3,
0,4,4,4,5,5,5,6,6,6,
0,4,4,4,5,5,5,6,6,6,
0,4,4,4,5,5,5,6,6,6,
0,7,7,7,8,8,8,9,9,9,
0,7,7,7,8,8,8,9,9,9,
0,7,7,7,8,8,8,9,9,9,
};
//void print()
//{
//  for(int i=1;i<=9;i++)
//    {
//          for(int j=1;j<=9;j++)
//          cout<<a[i][j]<<" ";
//      cout<<endl; 
//  }
//  cout<<endl;
//}
void dfs(int rm,int now) {
    if(rm==0) {flag=1; ans=max(ans,now); return;}
    if(now+rm*90<=ans) return;
    int tx=0,ty=0,mn=10,way=0,bc=0;
    for(register int i=1;i<=9;i++) //81格当中放那个数的方法最少找出来 
        for(register int j=1;j<=9;j++) 
        if(!a[i][j]) 
        {
            way=9,bc=ju[i][j];
            for(register int k=1;k<=9;k++) 
            {
                if(row[i][k] || col[j][k] || block[bc][k]) way--;
            }
            if(way<=mn) mn=way,tx=i,ty=j;
        }
    int tc=ju[tx][ty];
    for(register int i=1;i<=9;i++) //先放置可选择数目最少的空位,如果在上面可以记录可以放那些数更好 
        if(!row[tx][i] && !col[ty][i] && !block[tc][i])
        {
           a[tx][ty]=i;
           row[tx][i]=1;
           col[ty][i]=1; //row[][]...err
           block[tc][i]=1;
           //
//         cout<<tx<<" "<<ty<<endl;
//         print();
           //
           dfs(rm-1,now+a[tx][ty]*v[tx][ty]);
           row[tx][i]=0; 
           col[ty][i]=0; 
           block[tc][i]=0;
           a[tx][ty]=0;
        }
}
int main()
{
//    freopen("shudu.txt","r",stdin);

    for(int i=1;i<=9;i++) 
        for(int j=1;j<=9;j++) 
        {
            scanf("%d",&a[i][j]);
            if(a[i][j]>0) 
            {
                ans+=a[i][j]*v[i][j]; 
                row[i][a[i][j]]=1; 
                col[j][a[i][j]]=1;
                block[ju[i][j]][a[i][j]]=1;
                t--;
            }
        }
    dfs(t,ans);
    if(flag) printf("%d\n",ans);
    else printf("-1\n");
//    cout<<clock()<<endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值