【NOIP2009】靶形数独

搜索绝对是解决数独问题的一大利器。

我们将不完整的数独读入。如果爆搜的话显然凉凉O(2^81)?

想一下人类在玩数独的时候会怎样——找出填数比较多的行与列的交点,因为这样能排除更多的非法选择。

放到搜索上就能减小搜索树的规模,降低时间复杂度。

我们统计每一行、每一列已经填完的数的数量,再统计每一行、每一列、每一小区域当中某一个数是否出现。

每一次填数之前,找已经填数最多的一行与最多的一列的交点填(如果还没填的话),当数独都填完了以后统计一下得分即可

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int a[10][10],h[10][10],s[10][10],f[10][10];
 4 int hnum[10],snum[10];
 5 int ans=-1,num; 
 6 int calc(int i,int j)
 7 {
 8     return (i-1)/3*3+1+(j-1)/3;
 9 }
10 int sum[10][10]=
11 {
12     {0,0,0,0,0,0,0,0,0,0},
13     {0,6,6,6,6,6,6,6,6,6},
14     {0,6,7,7,7,7,7,7,7,6},
15     {0,6,7,8,8,8,8,8,7,6},
16     {0,6,7,8,9,9,9,8,7,6},
17     {0,6,7,8,9,10,9,8,7,6},
18     {0,6,7,8,9,9,9,8,7,6},
19     {0,6,7,8,8,8,8,8,7,6},
20     {0,6,7,7,7,7,7,7,7,6},
21     {0,6,6,6,6,6,6,6,6,6},
22 };
23 inline int total()
24 {
25     int aaa=0;
26     for(int i=1;i<=9;i++)
27         for(int j=1;j<=9;j++)
28             aaa+=a[i][j]*sum[i][j];
29     return aaa;
30 }
31 void dfs(int x,int y,int z)
32 {
33     if(z==81)
34     {
35         ans=max(ans,total());
36         return ;
37     }
38     for(int k=1;k<=9;k++)
39     {
40         if(h[x][k]||s[y][k]||f[calc(x,y)][k]) continue ;
41         h[x][k]=1;
42         s[y][k]=1;
43         f[calc(x,y)][k]=1;
44         a[x][y]=k;
45         hnum[x]++;
46         snum[y]++;
47         int xx=0,yy=0;
48         int maxx=-1,maxy=-1;
49         for(int i=1;i<=9;i++)
50             if(hnum[i]>maxx&&hnum[i]<9) maxx=hnum[i],xx=i;
51         for(int j=1;j<=9;j++)
52             if(snum[j]>maxy&&!a[xx][j]) maxy=snum[j],yy=j;
53         dfs(xx,yy,z+1);
54         h[x][k]=0;
55         s[y][k]=0;
56         f[calc(x,y)][k]=0;
57         hnum[x]--;
58         snum[y]--;
59         a[x][y]=0;
60     }
61 }
62 int main()
63 {
64     ios::sync_with_stdio(false);
65     for(int i=1;i<=9;i++)
66         for(int j=1;j<=9;j++)
67         {
68             cin>>a[i][j];
69             if(a[i][j]!=0)
70             {
71                 h[i][a[i][j]]=1;
72                 s[j][a[i][j]]=1;
73                 f[calc(i,j)][a[i][j]]=1;
74                 num++;
75                 hnum[i]++;
76                 snum[j]++;
77             }
78         }
79     int x=0,y=0,maxx=-1,maxy=-1;
80     for(int i=1;i<=9;i++)
81         if(hnum[i]>maxx&&hnum[i]<9) maxx=hnum[i],x=i;
82     for(int j=1;j<=9;j++)
83         if(snum[j]>maxy&&!a[x][j]) maxy=snum[j],y=j;
84     dfs(x,y,num);
85     cout<<ans;
86     return 0;
87 }
AC Code
原文地址:https://www.cnblogs.com/shl-blog/p/10583888.html