洛谷 1074 [NOIP2009] 靶形数独 dfs+剪枝
2017-09-23 22:07
295 查看
题目:
https://www.luogu.org/problem/show?pid=1074
自己的代码70分(玄学倒搜);
改不出来看题解,长见识;
70分
正搜40,倒搜70,codevs卡时95!
正解:
启发式搜索+状压;
sum_hang[i] : 第i行大于0的数的个数;
lie[i]:第i列使用的数(状压);
hang[i]:第i行使用的数(状压);
ge[i]:第i个九宫个使用的数(状压);
ma:输入;
sum:得分;
un:没有填的格子的位置;
cnt:没填的格子个数;
思路:
预处理;
跳着搜每个没有填的位置,若全搜完即得到一个解;
这里的启发函数的意义:优先搜候选数少的格子,可以减少搜索树的大小;
状压:
对于某列111111001表示7,8个空没有填数;算是卡常吧;
收获:
1. |的回溯用^;
2. 搜索可以跳着搜……;
3. 重载运算符的新姿势;
好像可以用跳舞链做(也就比这份代码快一点点),但是不会,%会的dalao;
https://www.luogu.org/problem/show?pid=1074
自己的代码70分(玄学倒搜);
改不出来看题解,长见识;
70分
正搜40,倒搜70,codevs卡时95!
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int ma[10][10],ans=-1,cnt,sum[10][10]; bool can(int x,int y,int now) { int fx=0,fy=0; if(x<=3) fx=1; else if(x<=6) fx=4; else fx=7; if(y<=3) fy=1; else if(y<=6) fy=4; else fy=7; for(int i=1;i<=9;i++) if(ma[x][i]==now || ma[i][y]==now) return false; for(int i=fx;i<=fx+2;i++) for(int j=fy;j<=fy+2;j++) if(ma[i][j]==now) return false; return true; } void dfs(int x,int tot) { int fx=0,fy=0; if(x==0) { ans=max(ans,tot); return; } if(x%9==0) fx=x/9; else fx=x/9+1; fy=x-(fx-1)*9; if(ma[fx][fy]) dfs(x-1,tot+sum[fx][fy]*ma[fx][fy]); else for(int i=1;i<=9;i++) { if(can(fx,fy,i)) { ma[fx][fy]=i; dfs(x-1,tot+sum[fx][fy]*ma[fx][fy]); ma[fx][fy]=0; } } return; } void ji() { for(int i=1;i<=9;i++) for(int j=1;j<=9;j++) sum[i][j]+=6; for(int i=2;i<=8;i++) for(int j=2;j<=8;j++) sum[i][j]+=1; for(int i=3;i<=7;i++) for(int j=3;j<=7;j++) sum[i][j]+=1; for(int i=4;i<=6;i++) for(int j=4;j<=6;j++) sum[i][j]+=1; sum[5][5]++; return; } void solve() { int ss[10][10]; for(int i=1;i<=9;i++) for(int j=1;j<=9;j++) scanf("%d",&ma[i][j]); ji(); dfs(81,0); return; } int main() { solve(); cout<<ans; return 0; }
正解:
启发式搜索+状压;
sum_hang[i] : 第i行大于0的数的个数;
lie[i]:第i列使用的数(状压);
hang[i]:第i行使用的数(状压);
ge[i]:第i个九宫个使用的数(状压);
ma:输入;
sum:得分;
un:没有填的格子的位置;
cnt:没填的格子个数;
思路:
预处理;
跳着搜每个没有填的位置,若全搜完即得到一个解;
这里的启发函数的意义:优先搜候选数少的格子,可以减少搜索树的大小;
状压:
对于某列111111001表示7,8个空没有填数;算是卡常吧;
收获:
1. |的回溯用^;
2. 搜索可以跳着搜……;
3. 重载运算符的新姿势;
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int MAXN=1001,tmp=(1<<9)-1; int sum_hang[MAXN],lie[MAXN],hang[MAXN],ge[MAXN],ma[MAXN][MAXN],sum[MAXN][MAXN]; int cnt,ans=-1,tot,num; struct hh { int x,y; bool operator < (hh t) const { if(sum_hang[x]==sum_hang[t.x]) return x < t.x; return sum_hang[x]>sum_hang[t.x]; } }un[MAXN]; void ji() { for(int i=0;i<9;i++) for(int j=0;j<9;j++) sum[i][j]+=6; for(int i=1;i<8;i++) for(int j=1;j<8;j++) sum[i][j]+=1; for(int i=2;i<7;i++) for(int j=2;j<7;j++) sum[i][j]+=1; for(int i=3;i<6;i++) for(int j=3;j<6;j++) sum[i][j]+=1; sum[4][4]++; return; } int gets(int x,int y) { return (x/3*3)+(y/3);//第几个九宫格; } void dfs(int cur,int tot) { if(cur>cnt) { ans=max(ans,tot); return; } int x=un[cur].x,y=un[cur].y; int temp=(hang[x]|(lie[y]|ge[gets(x,y)]));//寻找可用的数,简洁迅速; if(temp==tmp) return; for(int i=1;i<=9;i++) { if(!((temp>>(i-1))&1)) { int ss=1<<(i-1); ma[x][y]=i; hang[x]|=ss; lie[y]|=ss; ge[gets(x,y)]|=ss; dfs(cur+1,tot+ma[x][y]*sum[x][y]); hang[x]^=ss;//回溯用^; lie[y]^=ss; ge[gets(x,y)]^=ss; ma[x][y]=0; } } return; } void solve() { ji(); for(int i=0;i<9;i++) for(int j=0;j<9;j++) { scanf("%d",&ma[i][j]); if(ma[i][j]) { num+=ma[i][j]*sum[i][j]; hang[i]|=(1<<(ma[i][j]-1)); lie[j]|=(1<<(ma[i][j]-1)); ge[gets(i,j)]|=(1<<(ma[i][j]-1)); sum_hang[i]++; } } for(int i=0;i<9;i++) for(int j=0;j<9;j++) if(!ma[i][j]) cnt++,un[cnt].x=i,un[cnt].y=j; sort(un+1,un+cnt+1);//优先级排序; dfs(1,num); cout<<ans; } int main() { solve(); return 0; }
好像可以用跳舞链做(也就比这份代码快一点点),但是不会,%会的dalao;
相关文章推荐
- 【NOIP2009】洛谷1074 靶形数独
- 【NOIP2009】【CJOJ1687】【洛谷1074】靶形数独
- LuoguP1074[NOIP2009] 靶形数独 解题报告【搜索】
- noip 2009 靶形数独
- 【NOIP2009】靶形数独 DLX(Dancing Links)
- NOIP 2009 靶形数独
- 【NOIP 2009 提高组】靶形数独
- [NOIP2009]靶形数独【搜索】
- noip2009 靶形数独
- [NOIP2009]潜伏者,Hankson's Problem,最优贸易,靶形数独
- [noip2009]靶形数独
- [NOIP2009]靶形数独 深搜+枝杈优化
- Noip 2009 解题报告(潜伏着,Hankson的趣味题,最优贸易,靶形数独)
- 洛谷P1074 [Noip2009]靶形数独
- NOIP2009靶形数独——位运算优化DFS
- 大暴搜 [NOIP2009]靶形数独
- 洛谷 1074 靶形数独
- NOIP2009 靶形数独
- NOIP2009 靶形数独
- 【题】【搜索(预处理剪枝)】NOIP2009 靶形数独