题意:
小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他们想用数独来一比高低。但普通的数独对他们来说都过于简单了,于是他们向Z博士请教,Z博士拿出了他最近发明的“靶形数独”,作为这两个孩子比试的题目。
靶形数独的方格同普通数独一样,在9格宽×9格高的大九宫格中有9个3格宽×3格高的小九宫格(用粗黑色线隔开的)。在这个大九宫格中,有一些数字是已知的,根据这些数字,利用逻辑推理,在其他的空格上填入1到9的数字。每个数字在每个小九宫格内不能重复出现,每个数字在每行、每列也不能重复出现。但靶形数独有一点和普通数独不同,即每一个方格都有一个分值,而且如同一个靶子一样,离中心越近则分值越高。(如图)
上图具体的分值分布是:最里面一格(黄***域)为10分,黄***域外面的一圈(红***域)每个格子为9分,再外面一圈(蓝***域)每个格子为8分,蓝***域外面一圈(棕***域)每个格子为7分,最外面一圈(白***域)每个格子为6分,如上图所示。比赛的要求是:每个人必须完成一个给定的数独(每个给定数独有可能有不同的填法),而且要争取更高的总分数。而这个总分数即每个方格上的分值和完成这个数独时填在相应格上的数字的乘积的总和。如图,在以下这个已经填完数字的靶形数独游戏中,总分为2829。游戏规定,将以总分数的高低决出胜负。
由于求胜心切,小城找到了善于编程的你,让你帮他求出,对于给定的靶形数独,能够得到的最高分数。
题解:
这个题目其实不难,就是很复杂而已,你要把所有的状态都给枚举出来的话,那毫无疑问,肯定会超时,所以我们这里有个小技巧:
这里我是按行枚举的,所以有个小技巧,我们先枚举每行剩余0少的个数,这样开始枚举的话,可以使递归层数大大减少,所以我们用个b结构体记录行号和相应0的个数,按照个数由小到大排序,然后按照先枚举少的行数开始进行递归。
/*Keep on going Never give up*/ #pragma GCC optimize(3,"Ofast","inline") #include <bits/stdc++.h> const int maxn = 1e4+10; const int MaxN = 0x3f3f3f3f; const int MinN = 0xc0c0c00c; typedef long long ll; const int mod = 100000000; using namespace std; int a[20][20]; int visited[20][20]; struct point{ int num; int ans; }; point b[20]; int imax=0; struct rule{ bool operator ()(const point & a,const point & b){ return a.ans<b.ans; } }; bool che(int i,int f,int num){ for(int k=1;k<=9;k++){ if(num==a[i][k]||num==a[k][f]){ return false; } } int x=((i-1)/3)*3+1; int y=((f-1)/3)*3+1; for(int ii=x;ii<x+3;ii++) for(int ff=y;ff<y+3;ff++){ if(num==a[ii][ff]) return false; } return true; } void dfs(int i,int f){ if(i==10){ int nowmax=0; for(int i=1;i<=9;i++) for(int f=1;f<=9;f++){ int flag=min(i,f); int flag1=max(i,f); if(flag==1||flag1==9) nowmax+=a[i][f]*6; else if(flag==2||flag1==8) nowmax+=a[i][f]*7; else if(flag==3||flag1==7) nowmax+=a[i][f]*8; else if(flag==4||flag1==6) nowmax+=a[i][f]*9; else nowmax+=a[i][f]*10; } if(nowmax>imax) imax=nowmax; return ; } if(a[b[i].num][f]!=0){ if(f==9) dfs(i+1,1); else dfs(i,f+1); } else{ for(int k=1;k<=9;k++){ if(che(b[i].num,f,k)){ a[b[i].num][f]=k; if(f==9) dfs(i+1,1); else dfs(i,f+1); a[b[i].num][f]=0; } } } } int main() { int i,f; for(i=1;i<=9;i++){ int ans=0; for(f=1;f<=9;f++){ scanf("%d",&a[i][f]); if(a[i][f]==0) ans++; } b[i].ans=ans,b[i].num=i; } sort(b+1,b+10,rule()); dfs(1,1); if(imax==0) imax=-1; printf("%d",imax); return 0; }