幻方
【题目描述】
给定 N*N 个数,把它们填入 N*N 的方格中,使每行每列和两个对角线里数的和都相等。
数据保证有可行解,输出任一解即可。
【输入格式】
第一行一个整数 N。
第二行 N*N 个整数,表示要填入幻方中的数。
【输出格式】
N 行,每行 N 个整数,代表填好的幻方
【样例输入】
3
1 2 3 4 5 6 7 8 9
【样例输出】
3
2 7 6
9 5 1
4 3 8
大致是一行一行枚举搜
要加上各种减支
1.一行的和不为lim
2.开始预处理出单个数字可以参与多少和为lim的方案f[i]
显然对角线要求f[i]>3
3.改变搜索顺序,按f从小到大排序,不过这应该没什么用
4.在倒数第2行时判断最后一行可以使这一列的和等于lim,无法就不需要枚举后面的点了
(这是很重要的剪枝)
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<ctime> 6 using namespace std; 7 struct XXX 8 { 9 long long x; 10 int f; 11 } a[17]; 12 int n; 13 long long s[5][5],sumx[5],sumy[5],lim; 14 bool vis[17]; 15 bool cmp(XXX x,XXX y) 16 { 17 return x.f>y.f; 18 } 19 bool judge(int y) 20 {int i; 21 for (i=1;i<=n*n;i++) 22 if (vis[i]==0&&sumy[y]+a[i].x==lim) return 0; 23 return 1; 24 } 25 void dfs(int x,int y) 26 { 27 int i,j; 28 if (y>n) 29 { 30 if (sumx[x]!=lim) return; 31 dfs(x+1,1); 32 return; 33 } 34 if (x>n) 35 { 36 long long s1=0,s2=0; 37 for (i=1; i<=n; i++) 38 s1+=s[i][n-i+1],s2+=s[i][i]; 39 if (s1!=s2) return; 40 else if (s1==s2&&s1==lim) 41 { 42 for (i=1; i<=n; i++) 43 { 44 for (j=1; j<=n; j++) 45 printf("%lld ",s[i][j]); 46 printf("\n"); 47 } 48 exit(0); 49 } 50 return; 51 } 52 for (i=1; i<=n*n; i++) 53 if (vis[i]==0) 54 { 55 if (x==n) 56 { 57 if (sumy[y]+a[i].x==lim) 58 { 59 s[x][y]=a[i].x; 60 sumx[x]+=a[i].x; 61 sumy[y]+=a[i].x; 62 vis[i]=1; 63 if ((x==y||x==n-y+1)&&a[i].f<3); 64 else 65 dfs(x,y+1); 66 sumx[x]-=a[i].x; 67 sumy[y]-=a[i].x; 68 vis[i]=0; 69 } 70 } 71 else 72 { 73 s[x][y]=a[i].x; 74 sumx[x]+=a[i].x; 75 sumy[y]+=a[i].x; 76 vis[i]=1; 77 if ((x==y||x==n-y+1)&&a[i].f<3); 78 else if (x==n-1&&judge(y)); 79 else 80 dfs(x,y+1); 81 sumx[x]-=a[i].x; 82 sumy[y]-=a[i].x; 83 vis[i]=0; 84 } 85 } 86 } 87 int main() 88 { 89 int i,j,k,l; 90 cin>>n; 91 for (i=1; i<=n*n; i++) 92 { 93 scanf("%lld",&a[i].x); 94 lim+=a[i].x; 95 } 96 lim/=n; 97 if (n==4) 98 for (i=1; i<=n*n; i++) 99 { 100 for (j=i+1; j<=n*n; j++) 101 { 102 for (k=j+1; k<=n*n; k++) 103 { 104 for (l=k+1; l<=n*n; l++) 105 { 106 if (a[i].x+a[j].x+a[k].x+a[l].x==lim) 107 a[i].f++,a[j].f++,a[k].f++,a[l].f++; 108 } 109 } 110 } 111 } 112 if (n==3) 113 for (i=1; i<=n*n; i++) 114 { 115 for (j=i+1; j<=n*n; j++) 116 { 117 for (k=j+1; k<=n*n; k++) 118 { 119 if (a[i].x+a[j].x+a[k].x==lim) 120 a[i].f++,a[j].f++,a[k].f++; 121 } 122 } 123 } 124 sort(a+1,a+n*n+1,cmp); 125 dfs(1,1); 126 }