codevs 1174 靶形数独 2009年NOIP全国联赛提高组
2017-03-10 16:40
423 查看
咳咳,经过一个星期断断续续的痛苦挣扎终于把这个数独题改好了~
/当然是在参考了无数网上代码以后/
作为纯正的蒟蒻怎么能像YWQ同学那样作死地选择那个酷似十滴水代码三百多行又臭又长的舞蹈链呢?聪明的我果断选择暴搜~
当然暴搜是有技巧的,应该搜的同时判断并及时剪枝。同时还有一个技巧,如果某一个格子横行纵行小九宫格都要满足的情况下能填入的数最少,那就从它开始填比较快。
最后代码90行秒杀哈哈哈
/当然是在参考了无数网上代码以后/
作为纯正的蒟蒻怎么能像YWQ同学那样作死地选择那个酷似十滴水代码三百多行又臭又长的舞蹈链呢?聪明的我果断选择暴搜~
当然暴搜是有技巧的,应该搜的同时判断并及时剪枝。同时还有一个技巧,如果某一个格子横行纵行小九宫格都要满足的情况下能填入的数最少,那就从它开始填比较快。
最后代码90行秒杀哈哈哈
#include<cstdio> #include<cstring> #include<algorithm> #define ms(x,y) memset(x,y,sizeof(x)); #define inf 0x3fffffff using namespace std; int shudu[10][10],n,ans=0; bool F=false,H[10][10],L[10][10],A[10][10]; //H--行,L--列,A--小九宫格;H[i][j]=1,表示第i行能够填入数字j,其余以此类推。TRUE未填,FALSE已填 int At(int x,int y){ return (x-1)/3*3+(y+2)/3; }//确定(x,y)所在的小九宫格 int Abs(int a){ return a<0?-a:a; } int Score(int x,int y) { return 10-max(Abs(x-5),Abs(y-5)); }//计算(x,y)的分数 void init(){ for(int i=1;i<=9;i++) for(int j=1;j<=9;j++){ scanf("%d",&shudu[i][j]); ans+=shudu[i][j]*Score(i,j); } for(int i=1;i<=9;i++) for(int j=1;j<=9;j++) if(shudu[i][j]){ if(H[i][shudu[i][j]]&&L[j][shudu[i][j]]&&A[At(i,j)][shudu[i][j]]) H[i][shudu[i][j]]=L[j][shudu[i][j]]=A[At(i,j)][shudu[i][j]]=false; else{//如果读入的数已经自相矛盾可直接判无解 F=true; printf("-1"); return ; } } } void dfs(int marks){ int minn=inf,px=0,py=0,goal=0,num,K; for(int i=1;i<=9;i++) for(int j=1;j<=9;j++) if(!shudu[i][j]){ num=0; K=0; for(int k=1;k<=9;k++) if(H[i][k]&&L[j][k]&&A[At(i,j)][k]){ num++; K=k; } goal+=K*Score(i,j);//估计最高得分.(K一定是能填进里面的数中最大的) if(num<minn){ minn=num; px=i; py=j; }//若已知量极多,则从此处开始填 } if(goal+marks<=ans) return ;//剪枝 if(goal==0){ F=true;// 填完了 ans=max(ans,marks); return ; } if(num==0) return ; int at=At(px,py),score=Score(px,py); for(int i=1;i<=9;i++){ if(H[px][i]&&L[py][i]&&A[at][i]){ H[px][i]=L[py][i]=A[at][i]=false; shudu[px][py]=i; dfs(marks+i*score);//再来填下一个 shudu[px][py]=0; H[px][i]=L[py][i]=A[at][i]=true; } } return ; } int main(){ ms(H,true); ms(L,true); ms(A,true);//初始化全部都可以填 init(); if(F) return 0; dfs(ans); if(F) printf("%d",ans); else printf("-1"); return 0; }
相关文章推荐
- Codevs 1172 Hankson 的趣味题 2009年NOIP全国联赛提高组
- 靶形数独 2009年NOIP全国联赛提高组(搜索)
- Codevs 1171 潜伏者 2009年NOIP全国联赛提高组
- Codevs P1066 引水入城 2010年NOIP全国联赛提高组
- CODE[VS] 天梯 1098 均分纸牌 2002年NOIP全国联赛提高组
- 最短路 之 CODE[VS] 1041 Car的旅行路线 2001年NOIP全国联赛提高组
- Codevs 3731 寻找道路 2014年 NOIP全国联赛提高组
- codevs 1044 拦截导弹 1999年NOIP全国联赛提高组
- Codevs 1218 疫情控制 2012年NOIP全国联赛提高组
- 树形依赖背包(codevs1155 金明的预算方案 2006年NOIP全国联赛提高组)
- Codevs 1169 传纸条/1043 方格取数 2008/2000年NOIP全国联赛提高组 多线程dp
- 棋盘型动态规划 之 CODE[VS] 1169 传纸条 2008年NOIP全国联赛提高组
- 划分型动态规划 之 CODE[VS] 1039 数的划分 2001年NOIP全国联赛提高组
- 贪心 + 并查集 之 CODE[VS] 1069 关押罪犯 2010年NOIP全国联赛提高组
- Codevs 1138 聪明的质监员 2011年NOIP全国联赛提高组
- Codevs 1017 乘积最大 2000年NOIP全国联赛普及组NOIP全国联赛提高组
- 划分型动态规划 之 CODE[VS] 1017 乘积最大 2000年NOIP全国联赛提高组
- Codevs 1137 计算系数 2011年NOIP全国联赛提高组
- 【codevs黄金】1098 均分纸牌 2002年NOIP全国联赛提高组
- Codevs 1169 传纸条 2008年NOIP全国联赛提高组