codevs 1174 靶形数独
来源:互联网 发布:护照制作软件 编辑:程序博客网 时间:2024/05/17 07:28
去题面的传送门
QAQ这道题已经调了很久了,一直是TLE
第一次交,codevs 35分,洛谷 70分(好吧看到这样子我还以为洛谷的数据水来着)
后来加了一个优化,codevs 95分,洛谷 80分(这才知道其实是codevs数据水)
优化是这样的:
一开始读入之后,把所有没有填的空位,它的所在行、列、九宫格里的已经填了的数字统计一下,放到结构体里,然后按照数字数量由大到小排序(所在区域已经填了的数字越多,越优先搜索),dfs时按照结构体顺序搜索,改掉原来一行一行地搜索
但是这样肯定不行,因为我还是T了(╮(╯▽╰)╭)
想想这样做有什么缺点:
①只统计了数字个数,而不是已经填了的数字的种类
②随着搜索的进行,下一个搜索的最优目标可能会改变,这时,初始时设定的已经排列好的顺序就不是最优的了,还是会有很多冗杂的操作
所以,最后的优化就是,在搜索过程中,用函数计算下一个要搜索的点(其实是启发式搜索的启发函数)。计算的标准就是,改点所在的行、列、九宫格内,还没有没使用的数字的数量,越少越好
(虽然一开始觉得这样很暴力,但是可以让搜索树变得超级小)
一开始T掉的点跑了大约6秒(手动测),优化之后变成717ms,时间限制是4s
ps:启发式搜索还是要选好启发函数
代码:
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;int ans,cnt,sum;int ju[10][10],X[10][10],Y[10][10],S[10][10];bool vis[10][10],used[10][10];bool flg=0;struct hh{ int x,y;};int muti[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}};hh getit(){ hh ret; int cm=15,sum=0; for(int i=1;i<=9;++i) for(int j=1;j<=9;++j) if(!ju[i][j]) { sum=0; int wh=(i-1)/3*3+(j-1)/3+1; for(int k=1;k<=9;++k) if(!X[i][k]&&!Y[j][k]&&!S[wh][k]) sum++; if(sum<cm) { cm=sum; ret.x=i; ret.y=j; } } return ret;}void dfs(int x,int y,int k,int tot){ if(x>=1&&y<=9&&x<=9&&y>=1&&!vis[x][y]&&!used[x][y]) { int wh=(x-1)/3*3+(y-1)/3+1; for(int i=1;i<=9;++i) if(!X[x][i]&&!Y[y][i]&&!S[wh][i]) { X[x][i]=Y[y][i]=S[wh][i]=vis[x][y]=1; ju[x][y]=i; if(k==cnt) ans=max(ans,tot+i*muti[x][y]); else { hh xx=getit(); dfs(xx.x,xx.y,k+1,tot+ju[x][y]*muti[x][y]); } ju[x][y]=0; X[x][i]=Y[y][i]=S[wh][i]=vis[x][y]=0; } }}int main(){ for(int i=1;i<=9;++i) for(int j=1;j<=9;++j) { scanf("%d",&ju[i][j]); if(!ju[i][j]) { cnt++; continue; } sum+=ju[i][j]*muti[i][j]; used[i][j]=vis[i][j]=true; int wh=(i-1)/3*3+(j-1)/3+1; X[i][ju[i][j]]=S[wh][ju[i][j]]=Y[j][ju[i][j]]=1; } hh xx=getit(); dfs(xx.x,xx.y,1,sum); if(ans==0) ans--; printf("%d",ans); return 0;}
阅读全文
0 0
- CODEVS 1174 靶形数独
- codevs 1174 靶形数独
- 靶形数独 (codevs 1174)题解
- codevs 1174 靶形数独 (启发式搜索)
- 【wikioi】1174靶形数独
- codevs 1174 靶形数独 2009年NOIP全国联赛提高组
- Wiki OI 1174 靶形数独
- 【搜索】靶形数独
- 测试靶形数独
- 靶形数独
- 靶形数独
- 靶形数独
- NOIP2009 靶形数独
- NOIP2009 靶形数独
- [codevs1174] 靶形数独
- [vijos1755]靶形数独
- 靶形数独
- NOIP2009 靶形数独
- Android 使alertDialog.builder不会点击外面和按返回键消失
- BZOJ 1907 树的路径覆盖
- SIFT--关键点定位
- 在Ubuntu环境中QT支持c++11的方法
- c语言 利用分式前n项和求圆周率
- codevs 1174 靶形数独
- WM_CONCAT字符超过4000的处理办法
- 嫁给幸福 ——汪国真
- Screen 相关整理
- test
- 阿里云专有网络VPC使用教
- Webpack是什么(基本含义)
- 佛祖保护,代码永无bug
- UVA400 Unix ls