题解:
又是搜索- - 加状态压缩剪枝
二进制记下每行 每列 每个九宫格用过的数是谁 枚举的时候可以O(1)判断冲突
还有个很重要的剪枝 把可能使用数字最少的格子先搜索
代码:
1 #include <cstdio> 2 #include <cstdlib> 3 #include <algorithm> 4 using std::sort; 5 const int N=82,n=9,val[10][10]={{0,0,0,0,0,0,0,0,0,0}, 6 {0,6,6,6,6,6,6,6,6,6}, 7 {0,6,7,7,7,7,7,7,7,6}, 8 {0,6,7,8,8,8,8,8,7,6}, 9 {0,6,7,8,9,9,9,8,7,6}, 10 {0,6,7,8,9,10,9,8,7,6}, 11 {0,6,7,8,9,9,9,8,7,6}, 12 {0,6,7,8,8,8,8,8,7,6}, 13 {0,6,7,7,7,7,7,7,7,6}, 14 {0,6,6,6,6,6,6,6,6,6}}; 15 struct info{ 16 int x,y,z; 17 info(const int a=0,const int b=0,const int c=0): 18 x(a),y(b),z(c){} 19 }im[10][10],v[N]; 20 int map[10][10],xx[10],yy[10],zz[10],ans,maxans,rem; 21 inline bool cmp(info a,info b){ return a.z>b.z || (a.z==b.z && a.x<b.x) || (a.z==b.z && a.x==b.x && a.y<b.y); } 22 void print(int t){ 23 printf("%d",t); 24 exit(0); 25 } 26 void makeim(){ 27 for (int i=1;i<=n;i++) 28 for (int j=1;j<=n;j++){ 29 im[i][j].x=i; 30 im[i][j].y=j; 31 if (i<=3){ 32 if (j<=3) im[i][j].z=1; 33 else if (j<=6) im[i][j].z=2; 34 else im[i][j].z=3; 35 }else if (i<=6){ 36 if (j<=3) im[i][j].z=4; 37 else if (j<=6) im[i][j].z=5; 38 else im[i][j].z=6; 39 }else{ 40 if (j<=3) im[i][j].z=7; 41 else if (j<=6) im[i][j].z=8; 42 else im[i][j].z=9; 43 } 44 } 45 } 46 void makexyz(){ 47 for (int i=1;i<=n;i++) 48 for (int j=1;j<=n;j++) 49 if (map[i][j]){ 50 if ((xx[im[i][j].x]>>(map[i][j]-1))&1) print(-1); 51 if ((yy[im[i][j].y]>>(map[i][j]-1))&1) print(-1); 52 if ((zz[im[i][j].z]>>(map[i][j]-1))&1) print(-1); 53 xx[im[i][j].x]|=1<<(map[i][j]-1); 54 yy[im[i][j].y]|=1<<(map[i][j]-1); 55 zz[im[i][j].z]|=1<<(map[i][j]-1); 56 } 57 } 58 void makev(){ 59 for (int i=1;i<=n;i++) 60 for (int j=1;j<=n;j++) v[(i-1)*n+j]=info(i,j,val[i][j]); 61 sort(v+1,v+82,cmp); 62 } 63 bool check(int x,int y,int z){ 64 --z; 65 if ((xx[im[x][y].x]>>z)&1) return 0; 66 if ((yy[im[x][y].y]>>z)&1) return 0; 67 if ((zz[im[x][y].z]>>z)&1) return 0; 68 return 1; 69 } 70 void add(int x,int y,int z,int bo){ 71 --z; 72 xx[im[x][y].x]+=bo*(1<<z); 73 yy[im[x][y].y]+=bo*(1<<z); 74 zz[im[x][y].z]+=bo*(1<<z); 75 } 76 int getsave(int t){ 77 int res=0; 78 for (;t;t>>=1) res+=t&1; 79 return res; 80 } 81 void search(){ 82 if (ans+rem*9<=maxans) return; 83 int x=0,y,z=0; 84 for (int i=1;i<=n;i++) 85 for (int j=1;j<=n;j++) 86 if (!map[i][j]){ 87 int save=getsave(xx[im[i][j].x]|yy[im[i][j].y]|zz[im[i][j].z]); 88 if (save==9) return; 89 if (save>z) z=save,x=i,y=j; 90 } 91 if (!x){ 92 if (maxans<ans) maxans=ans; 93 return; 94 } 95 for (int i=9;i;i--) 96 if (check(x,y,i)){ 97 rem-=i; 98 ans+=i*val[x][y]; 99 add(x,y,i,1); 100 map[x][y]=i; 101 search(); 102 map[x][y]=0; 103 add(x,y,i,-1); 104 ans-=i*val[x][y]; 105 rem+=i; 106 } 107 } 108 int main(){ 109 rem=45*9; 110 for (int i=1;i<=n;i++) 111 for (int j=1;j<=n;j++){ 112 scanf("%d",&map[i][j]); 113 rem-=map[i][j]; 114 ans+=map[i][j]*val[i][j]; 115 } 116 makeim(); 117 makexyz(); 118 makev(); 119 search(); 120 if (maxans) print(maxans); 121 puts("-1"); 122 }