[NOIP 2009]靶形數獨題解
阿新 • • 發佈:2018-09-27
root targe www. print scanf inline 枚舉 如何 oid
題目鏈接:點擊
題目的一些信息就不給了,點鏈接吧。
解題思路:
我總結為一個要點,一個優化:
要點:搜索順序不能
for(i=1;i<=9;i++) for(j=1;j<=9;j++)
這樣時間復雜度過不去。
如何搜索?
當做填數字一樣,每一個格子枚舉數組,從上到下,從左到右填過去。
優化:這真的是欺負我這種沒有玩過數獨的人。
從已經填數字多的一行填,對行排個序,雖然每個格子都要填,這樣每個格子能夠搜索的狀態數總體變少了,就行了。
代碼:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define R register int #define L inline int using namespace std; const int N=10; int a[N][N],line[N][N],list[N][N],nine[N][N]; int ans,flag,ned,cnt; struct T{ int p,w; }o[N*N]; bool cmp(T qq,T ee){ return qq.w>ee.w; } L judge(R x,R y){if(x<=3){ if(y<=3)return 1; if(y>=7)return 3; return 2; } if(x<=6&&x>=4){ if(y<=3)return 4; if(y>=7)return 6; return 5; } else { if(y<=3)return 7; if(y>=7)return 9;return 8; } } L pd(R x,R y){ if(x==1||y==1||x==9||y==9)return 6; if(x==2||y==2||x==8||y==8)return 7; if(x==3||y==3||x==7||y==7)return 8; if(x==4||y==4||x==6||y==6)return 9; return 10; } inline void dfs(R num,R tot,R x,R y){ if(num==81){ flag=1; ans=max(tot,ans); return; } if(y==10) dfs(num,tot,x+1,1); else if(a[o[x].p][y]) dfs(num,tot,x,y+1); else { R root=judge(o[x].p,y); for(R i=1;i<=9;++i){ if(!line[o[x].p][i]&&!list[y][i]&&!nine[root][i]){ line[o[x].p][i]=list[y][i]=nine[root][i]=1; if(num==81){ flag=1; ans=max(tot,ans); line[o[x].p][i]=list[y][i]=nine[root][i]=0; return; } dfs(num+1,tot+i*pd(o[x].p,y),x,y+1); line[o[x].p][i]=list[y][i]=nine[root][i]=0; } } } } int main(){ for(R i=1;i<=9;++i) for(R j=1;j<=9;++j){ o[i].p=i; scanf("%d",&a[i][j]); if(a[i][j]){ cnt++; o[i].w++; ans+=pd(i,j)*a[i][j]; line[i][a[i][j]]=1; list[j][a[i][j]]=1; nine[judge(i,j)][a[i][j]]=1; } } sort(o+1,o+9+1,cmp); ned=ans; dfs(cnt,ned,1,1); if(!flag) printf("-1"); else printf("%d",ans); return 0; }
[NOIP 2009]靶形數獨題解