题目:
1:每行每列每个对角线的数字之和为sum / n
2:因为要按字典序输出,所以要从小到大枚举每个数
3:枚举完每行/列/对角线判断是否符合要求
- #include
- #include
- #include
- #include
-
- using namespace std;
-
- const int N = 5;
-
- int n;
- int sum;
- int w[N * N];
- bool st[N * N];
- int ans[N][N];
-
- bool check(int x, int y, int k)
- {
- if (y == n - 1)//判断是不是第x行已经全部枚举完
- {
- int sum1 = w[k];
- for (int i = 0; i < n - 1; i ++ ) sum1 += ans[x][i];
-
- if (sum != sum1) return false;
- }
-
- if (x == n - 1)//判断是不是第y列全部枚举完
- {
- int sum1 = w[k];
- for (int i = 0; i < n - 1; i ++ ) sum1 += ans[i][y];
-
- if (sum != sum1) return false;
- }
-
- if (x == n - 1 && y == 0)//反对角线
- {
- int sum1 = w[k];
- for (int i = 0; i < n - 1; i ++ ) sum1 += ans[i][n - i - 1];
-
- if (sum != sum1) return false;
- }
-
- if (x == n - 1 && y == n - 1)//正对角线
- {
- int sum1 = w[k];
- for (int i = 0; i < n; i ++ ) sum1 += ans[i][i];
-
- if (sum != sum1) return false;
- }
-
- return true;
- }
-
- void dfs(int x, int y)//(x, y)表示当前正在枚举x, y坐标
- {
- if (x == n)//枚举完了所有格子
- {
- cout << sum << endl;
- for (int i = 0; i < n; i ++ )
- {
- for (int j = 0; j < n; j ++ )
- printf("%d ", ans[i][j]);
- puts("");
- }
-
- exit(0);
- }
-
- for (int i = 0; i < n * n; i ++ )
- if (!st[i])
- {
- if (!check(x, y, i)) continue;//在枚举完本行/列/对角线之前判断是否符合条件
-
- st[i] = true;
-
- ans[x][y] = w[i];//在(x, y)这个坐标上选择w[i]
- if (y == n - 1) dfs(x + 1, 0);//说明枚举完了当前行的所有列, 枚举下一行
- else dfs(x, y + 1);//枚举下一列
-
- st[i] = false;//回溯
- }
-
- return ;
- }
-
- int main()
- {
- cin >> n;
- for (int i = 0; i < n * n; i ++ )
- {
- scanf("%d", &w[i]);
- sum += w[i];
- }
-
-
- sum = sum / n;//每行,每列,每个对角线的总和
- sort(w, w + n * n);//按照字典序输出,要从小到大枚举
-
- dfs(0, 0);
-
- return 0;
- }