从wyh大佬那里蹭来了一份dlx的题解,然后进行了一番深刻的理解,最后自己手打了一遍,感觉受益颇多,最主要的是这个代码融合了很多卡常技巧2333333333
和普通的dfs不同,这份代码从根进行剪枝,每一层都取方案数最小的位置进行搜索,因而得到十分显著的优化,原来一个点4s的题,现在20个点总共用时加起来也就3.7s
ps:其实应该把dl去了,因为这个地方只用到x算法,并没加十字链表╮(╯▽╰)╭
#include<iostream> #include<cstdio> #include<algorithm> #define ri register int using namespace std; int mmp[10][10],s[10][10],su,ans,tot; bool h[10][10],l[10][10],ku[10][10],u[10][10],flag; inline void re(int &a) { char x=getchar(); bool flag=0; while(x<'0'||x>'9') { if(x=='-') flag=1; x=getchar(); } while(x>='0'&&x<='9') a=a*10+x-'0',x=getchar(); if(flag) a*=-1; } inline void wr(int a) { if(a<0) putchar('-'),a*=-1; if(a/10) wr(a/10); putchar((a-a/10*10)+'0'); } inline void init() { for(ri i=1;i<=9;i++) for(ri j=1;j<=9;j++) { if(i==1||i==9||j==1||j==9) s[i][j]=6; else if(i==2||i==8||j==2||j==8) s[i][j]=7; else if(i==3||i==7||j==3||j==7) s[i][j]=8; else if(i==4||i==6||j==4||j==6) s[i][j]=9; else s[i][j]=10; } } inline int ask(int i,int j) { if(i<=3) { if(j<=3) return 1; else if(j<=6) return 2; else return 3; } else if(i<=6) { if(j<=3) return 4; else if(j<=6) return 5; else return 6; } else { if(j<=3) return 7; else if(j<=6) return 8; else return 9; } } void dfs(int he,int ci) { if(ci==81) { flag=1; ans=max(ans,he); return; } int lx,ly,tail=100,lin; for(ri i=1;i<=9;i++) for(ri j=1;j<=9;j++) { if(!u[i][j]) { lin=0; for(ri k=1;k<=9;k++) if(!h[i][k]&&!l[j][k]&&!ku[ask(i,j)][k]) lin++; if(lin<tail) tail=lin,lx=i,ly=j; } } for(ri i=1;i<=9;i++) if(!h[lx][i]&&!l[ly][i]&&!ku[ask(lx,ly)][i]) { h[lx][i]=l[ly][i]=ku[ask(lx,ly)][i]=u[lx][ly]=1; dfs(he+s[lx][ly]*i,ci+1); h[lx][i]=l[ly][i]=ku[ask(lx,ly)][i]=u[lx][ly]=0; } } int main() { init(); for(ri i=1;i<=9;i++) for(ri j=1;j<=9;j++) { re(mmp[i][j]); if(mmp[i][j]) { tot++; su+=s[i][j]*mmp[i][j]; h[i][mmp[i][j]]=1,u[i][j]=1,l[j][mmp[i][j]]=1,ku[ask(i,j)][mmp[i][j]]=1; } } ans=-1; dfs(su,tot); wr(ans); }