传送门
NOIP 2009 T4 靶形数独
题解:暴搜,注意优化:
1.先填能选的比较少的格子
2.好像可以用链表剪枝,留坑待填(一时半会儿估计都填不好,有兴趣的读者可自行yy,祝你们顺利╮(╯_╰)╭)
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN=10;
int cnt=0,mp[MAXN][MAXN],ans=-1;
bool h[MAXN][MAXN],l[MAXN][MAXN],f[MAXN][MAXN],vis[MAXN*MAXN];
int x[MAXN*MAXN],y[MAXN*MAXN];
int bel[MAXN][MAXN]={
{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},
};
int val[MAXN][MAXN]={
{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},
};
/*void print() {
for (int i=1;i<=9;++i) {
for (int j=1;j<=9;++j)
printf("%d ",mp[i][j]);
puts("");
}
puts("");
}*/
void dfs(int step) {
if (step>cnt) {
int sum=0;
for (int i=1;i<=9;++i)
for (int j=1;j<=9;++j)
sum+=mp[i][j]*val[i][j];
ans=max(ans,sum);
return ;
}
int mn=0x3f3f3f3f,pos;
for (int i=1;i<=cnt;++i) {
if (!vis[i]) {
int temp=0;
for (int j=1;j<=9;++j)
if (!h[x[i]][j]&&!l[y[i]][j]&&!f[bel[x[i]][y[i]]][j])
if (++temp==mn) break;
if (temp<mn) pos=i,mn=temp;
}
}
vis[pos]=true;
for (int j=1;j<=9;++j) {
if (!h[x[pos]][j]&&!l[y[pos]][j]&&!f[bel[x[pos]][y[pos]]][j]) {
h[x[pos]][j]=l[y[pos]][j]=f[bel[x[pos]][y[pos]]][j]=true;
mp[x[pos]][y[pos]]=j;//print();
dfs(step+1);
h[x[pos]][j]=l[y[pos]][j]=f[bel[x[pos]][y[pos]]][j]=false;
}
}
vis[pos]=false;
}
int main() {
// freopen("P1074.in","r",stdin);
memset(h,false,sizeof(h));
memset(l,false,sizeof(l));
memset(f,false,sizeof(f));
for (int i=1;i<=9;++i)
for (int j=1;j<=9;++j) {
scanf("%d",&mp[i][j]);
if (mp[i][j]) h[i][mp[i][j]]=l[j][mp[i][j]]=f[bel[i][j]][mp[i][j]]=true;
else x[++cnt]=i,y[cnt]=j,vis[cnt]=false;
}
dfs(1);
printf("%d\n",ans);
return 0;
}