编程题目《NOIP2009_T4_靶形数独》总结(不可思议的一道题)

来源:互联网 发布:攻城掠地神兵锻造数据 编辑:程序博客网 时间:2024/05/20 08:23

编程题目《NOIP2009_T4_靶形数独》总结(不可思议的一道题) - 哭,等谁回眸 - 哭,等谁回眸
编程题目《NOIP2009_T4_靶形数独》总结(不可思议的一道题) - 哭,等谁回眸 - 哭,等谁回眸
编程题目《NOIP2009_T4_靶形数独》总结(不可思议的一道题) - 哭,等谁回眸 - 哭,等谁回眸
编程题目《NOIP2009_T4_靶形数独》总结(不可思议的一道题) - 哭,等谁回眸 - 哭,等谁回眸
 
爆搜加优化!
代码如下:
#include<iostream>#include<algorithm>#include<cstring>#include<cmath>#include<queue>#include<vector>#include<cstdio>#include<cstdlib>using namespace std;const int s[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};//每个九宫格的预处理。const int p[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};//分值。bool line[10][10],row[10][10],ss[10][10],c[10][10];int xx,yy,n,num,i,j,ans,k,m,now,last,cnt,a[10][10],f[10][10];//f是限制数组。struct dong{int x,y;}d[100];//d为枚举顺序。inline void zbj(int i,int j)//找到i,j九宫格的左上角。笨方法!!{if(i<=3) xx=1;else {if(i<=6) xx=4;else xx=7;}if(j<=3) yy=1;else {if(j<=6) yy=4;else yy=7;}} inline void nyh(int k)//寻找第k多0的位置。{int max=0,x,y,i,j;for(i=1;i<=9;i++)for(j=1;j<=9;j++)if(c[i][j]&&f[i][j]>max) {max=f[i][j];x=i;y=j;}d[k].x=x;d[k].y=y;for(i=1;i<=9;i++){f[i][y]++;f[x][i]++;}zbj(x,y);for(i=xx;i<=xx+2;i++)//同main中的预处理。for(j=yy;j<=yy+2;j++)f[i][j]++;c[x][y]=false;}  void lyd(int k)//dfs{if(k==num+1)//边界。{if(now>ans) ans=now;return;}  int x=d[k].x;int y=d[k].y;for(int i=1;i<=9;i++)if(line[x][i]&&row[y][i]&&ss[s[x][y]][i])                        {now+=i*p[x][y];line[x][i]=false;row[y][i]=false;ss[s[x][y]][i]=false;lyd(k+1);//递归!now-=i*p[x][y];//以下为回溯。line[x][i]=true;row[y][i]=true;ss[s[x][y]][i]=true;}}int main(){memset(line,1,sizeof(line));//line标记列。memset(row,1,sizeof(row));//row标记行memset(ss,1,sizeof(ss));//ss预处理该九宫格。for(i=1;i<=9;i++)for(j=1;j<=9;j++){scanf("%ld",&a[i][j]);if(a[i][j]>0) {line[i][a[i][j]]=false;row[j][a[i][j]]=false;ss[s[i][j]][a[i][j]]=false;last+=a[i][j]*p[i][j];//以上是对已有的分值进行预处理。for(k=1;k<=9;k++){f[i][k]++;f[k][j]++;}zbj(i,j);for(k=xx;k<=xx+2;k++)for(m=yy;m<=yy+2;m++)f[k][m]++;                                   }else {num++;c[i][j]=true;}}for(i=1;i<=num;i++) nyh(i);//对于没有处理的数,从简单的(多0的)先来填补,附加上数独的规则即可。ans=-1;lyd(1);if(ans==-1) last=0;printf("%ld\n",ans+last);return 0;}


先说题,裸搜谁都会,但是至于优化,其实我也说不出来,我的不同在于使用了一个f数组来限制我的dfs,从而使时间缩短,不过具体这个f我也用的迷迷糊糊的,只能说是运气好,蒙对了,其他的就没什么可说的了,比赛时我自诩也打不出这样的代码,还是裸搜的性价比更高一些,也能拿到比较实惠的分数。
这道题同学都说很难,但我不觉的,可能是因为运气吧,但是我觉得有以下几点:①dfs我已经有一段时间没有再练过了,再看到一个dfs的题,之前在脑海里关于dfs的沉淀与大脑有了不错的磨合,所以做起来比较顺畅②我之前看过这道题,不过没有去写,只是偶尔的想想,比起那些非要在一天什么都不干也要A掉这道题的同学强,或许是当局者迷吧,再一看到这道题,以前的思路就源源不断的涌现出来了,所以,我认识到,平时的思考是非常重要的,它会在意想不到的地方带来意想不到的惊喜!
好了,这道题就到这里吧!
0 0
原创粉丝点击