您的位置:首页 > 其它

[NOIP2009]靶形数独【搜索】

2015-01-19 20:42 211 查看
(sudoku.pas/c/cpp)

【问题描述】

小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他

们想用数独来一比高低。但普通的数独对他们来说都过于简单了,于是他们向Z博士请教,

Z博士拿出了他最近发明的“靶形数独”,作为这两个孩子比试的题目。

靶形数独的方格同普通数独一样,在9格宽×9格高的大九宫格中有9个3格宽×3格

高的小九宫格(用粗黑色线隔开的)。在这个大九宫格中,有一些数字是已知的,根据这些

数字,利用逻辑推理,在其他的空格上填入1到9的数字。每个数字在每个小九宫格内不能

重复出现,每个数字在每行、每列也不能重复出现。但靶形数独有一点和普通数独不同,即

每一个方格都有一个分值,而且如同一个靶子一样,离中心越近则分值越高。(如图)

上图具体的分值分布是:最里面一格(黄色区域)为10分,黄色区域外面的一圈(红

色区域)每个格子为9分,再外面一圈(蓝色区域)每个格子为8分,蓝色区域外面一圈(棕

色区域)每个格子为7分,最外面一圈(白色区域)每个格子为6分,如上图所示。





比赛的要求是:每个人必须完成一个给定的数独(每个给定数独可能有不同的填法),而且要争取

更高的总分数。而这个总分数即每个方格上的分值和完成这个数独时填在相应格上的数字

的乘积的总和。

由于求胜心切,小城找到了善于编程的你,让你帮他求出,对于给定的靶形数独,能

够得到的最高分数。

解题思路:很显然的搜索题嘛。。。搜索题就是优化,剪枝的问题了。。比如我们可以预处理出待填数的位置,这个还是很有用的。。然后从填了比较多数的行、列和块开始填数,,(这个大概可以写一个估价函数?)还有用位运算可以快很多,,不过我的代码没有,,因为是以前写的。。另外各种倒着搜貌似都会更快(NOIP的惯例?)。。我的代码还有一个过不了的点,,每次搜索题都是这样。。。这题还有比较神的做法,,就是DancingLinks(反正我不会)。。。

代码(vijos 95分):

#include
#include
#include
#include
using namespace std;
struct dian{
int x,y,k;
};
typedef int ju[11][11];
ju a,uf,uh,ul;
dian d[100];
int i,j,ans=0,h,l,sum=0,f[10],hang[10],lie[10];
int cul(ju a)
{int sum=0,i,j;
for (i=1;i<=9;i++)
sum+=a[1][i]*6+a[9][i]*6;
for (i=2;i<=8;i++)
sum+=a[i][1]*6+a[i][9]*6+a[i][2]*7+a[i][8]*7;
for (i=3;i<=7;i++)
sum+=a[2][i]*7+a[8][i]*7+a[3][i]*8+a[7][i]*8;
for (i=4;i<=6;i++)
sum+=a[i][3]*8+a[i][7]*8+a[i][4]*9+a[i][6]*9;
sum+=a[4][5]*9+a[5][5]*10+a[6][5]*9;
return sum;
}
void dfs(dian k,int dd)
{if (dd==0) {ans=max(ans,cul(a));return;}
//printf("%d ",dd);
int h=(k.x-1)/3,l=(k.y-1)/3;
for (int i=1;i<=9;i++)
{//printf("%d %d %d\n",k.x,k.y,i);
if(uf[h*3+l+1][i]==0&&uh[k.x][i]==0&&ul[k.y][i]==0)
{uf[h*3+l+1][i]=1;uh[k.x][i]=1;ul[k.y][i]=1;
a[k.x][k.y]=i;
dfs(d[dd-1],dd-1);
uf[h*3+l+1][i]=0;uh[k.x][i]=0;ul[k.y][i]=0;
a[k.x][k.y]=0;
}
}
}
bool cmp(dian a,dian b) {return a.k
int main()
{freopen("sudoku.in","r",stdin);
memset(uf,0,sizeof(uf));
memset(uh,0,sizeof(uh));
memset(ul,0,sizeof(ul));
memset(f,0,sizeof(uf));
memset(hang,0,sizeof(hang));
memset(lie,0,sizeof(lie));
for (i=1;i<=9;i++)
for (j=1;j<=9;j++)
{scanf("%d",&a[i][j]);
h=(i-1)/3;l=(j-1)/3;
if (a[i][j]==0)
{d[++sum].x=i;
d[sum].y=j;
continue;
}
hang[i]++;lie[j]++;f[h*3+l+1]++;
uf[h*3+l+1][a[i][j]]=1;
uh[i][a[i][j]]=1;
ul[j][a[i][j]]=1;
}
int hh,ll;
for (i=1;i<=sum;i++)
{hh=(d[i].x-1)/3;ll=(d[i].y-1)/3;
d[i].k=f[hh*3+ll+1]+hang[d[i].x]+lie[d[i].y];
}
sort(d+1,d+1+sum,cmp);
dfs(d[sum],sum);
if (ans!=0) cout<<ans; else cout<<"-1";
fclose(stdin);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: