题目描述
填数字方格的游戏有很多种变化,如下图所示的 4 × 4 4 \times 4 4×4 方格中,我们要选择从数字 1 1 1 到 16 16 16 来填满这十六个格子( A i , j A_{i,j} Ai,j ,其中 i = 1 ⋯ 4 i=1 \cdots 4 i=1⋯4 , j = 1 ⋯ 4 j=1 \cdots 4 j=1⋯4)。为了让游戏更有挑战性,我们要求下列六项中的每一项所指定的四个格子,其数字累加的和必须为 34 34 34 :
A 1 , 1 A_{1,1} A1,1 | A 1 , 2 A_{1,2} A1,2 | A 1 , 2 A_{1,2} A1,2 | A 1 , 4 A_{1,4} A1,4 |
---|---|---|---|
A 2 , 1 A_{2,1} A2,1 | A 2 , 2 A_{2,2} A2,2 | A 2 , 3 A_{2,3} A2,3 | A 2 , 4 A_{2,4} A2,4 |
A 3 , 1 A_{3,1} A3,1 | A 3 , 2 A_{3,2} A3,2 | A 3 , 3 A_{3,3} A3,3 | A 3 , 4 A_{3,4} A3,4 |
A 4 , 1 A_{4,1} A4,1 | A 4 , 2 A_{4,2} A4,2 | A 4 , 3 A_{4,3} A4,3 | A 4 , 4 A_{4,4} A4,4 |
- 四个角落上的数字,即
A
1
,
1
+
A
1
,
4
+
A
4
,
1
+
A
4
,
4
=
34
A_{1,1}+A_{1,4}+A_{4,1}+A_{4,4}=34
A1,1+A1,4+A4,1+A4,4=34 。
- 每个角落上的
2
×
2
2 \times 2
2×2 方格中的数字,例如左上角
A
1
,
1
+
A
1
,
2
+
A
2
,
1
+
A
2
,
2
=
34
A_{1,1}+A_{1,2}+A_{2,1}+A_{2,2}=34
A1,1+A1,2+A2,1+A2,2=34 。
- 最中间的
2
×
2
2 \times 2
2×2 方格中的数字,即
A
2
,
2
+
A
2
,
3
+
A
3
,
2
+
A
3
,
3
=
34
A_{2,2}+A_{2,3}+A_{3,2}+A_{3,3}=34
A2,2+A2,3+A3,2+A3,3=34 。
- 每条水平线上四个格子中的数字,即
A
i
,
1
+
A
i
,
2
+
A
i
,
3
+
A
i
,
4
=
34
A_{i,1}+A_{i,2}+A_{i,3}+A_{i,4}=34
Ai,1+Ai,2+Ai,3+Ai,4=34,其中
i
=
1
⋯
4
i=1 \cdots 4
i=1⋯4 。
- 每条垂直线上四个格子中的数字,即
A
1
,
j
+
A
2
,
j
+
A
3
,
j
+
A
4
,
j
=
34
A_{1,j}+A_{2,j}+A_{3,j}+A_{4,j}=34
A1,j+A2,j+A3,j+A4,j=34,其中
j
=
1
⋯
4
j=1 \cdots 4
j=1⋯4 。
- 两条对角线上四个格子中的数字,例如左上角到右下角
A
1
,
1
+
A
2
,
2
+
A
3
,
3
+
A
4
,
4
=
34
A_{1,1}+A_{2,2}+A_{3,3}+A_{4,4}=34
A1,1+A2,2+A3,3+A4,4=34 。
- 右上角到左下角:
A
1
,
4
+
A
2
,
3
+
A
3
,
2
+
A
4
,
1
=
34
A_{1,4}+A_{2,3}+A_{3,2}+A_{4,1}=34
A1,4+A2,3+A3,2+A4,1=34 。
注意:特别的,我们会指定把数字 1 1 1 先固定在某一格内。
输入格式
输入只有一行包含两个正数据 i i i 和 j j j ,表示第 i i i 行和第 j j j 列的格子放数字 1 1 1。剩下的十五个格子,请按照前述六项条件用数字 2 2 2 到 16 16 16 来填满。
输出格式
输出四行,每行四个数,相邻两数之间用一个空格隔开,并且依序排好。排序的方式,是先从第一行的数字开始比较,每一行数字,由最左边的数字开始比,数字较小的解答必须先输出到文件中。
样例输入 #1
1 1
样例输出 #1
1 4 13 16
14 15 2 3
8 5 12 9
11 10 7 6
1 4 13 16
14 15 2 3
12 9 8 5
7 6 11 10
提示
数据规模
对于全部的测试点,保证 1 ≤ i , j ≤ 4 1 \leq i, j \leq 4 1≤i,j≤4。
Code
#include<bits/stdc++.h>
using namespace std;
int n,m,a[11][11],f[101],g[11],d=0;
void s(int x,int y) {
if(x==4&&y>4) { //目标解输出
for(int i=1; i<=4; i++) {
for(int j=1; j<=4; j++) if(j==4) cout<<a[i][j]<<endl;
else cout<<a[i][j]<<" ";
}
cout<<endl;
}
if(y>4) { //下一行
int z=0;
for(int i=1; i<=4; i++) z+=a[x][i];
if(z==34) s(x+1,1);//剪枝
return;
}
if(x==n&&y==m) { //是1就跳过
s(x,y+1);
return;
}
for(int i=2; i<=16; i++) if(f[i]==0) { //未使用
if(x==4) { //每条垂直线上四个格子中的数字是否等于34
int z=i;
for(int j=1; j<=3; j++) z+=a[j][y];
if(z!=34) continue;
}
if(x==4&&y==4) { //每四个角落上的数字是否等于34
int z=i+a[1][1]+a[4][1]+a[1][4];
if(z!=34) continue;
}
if(x==4&&y==1) { //右上角到左下角的数字是否等于34
int z=i+a[1][4]+a[2][3]+a[3][2];
if(z!=34) continue;
}
if(x==4&&y==4) { //每左上角到右下角的数字是否等于34
int z=i+a[1][1]+a[2][2]+a[3][3];
if(z!=34) continue;
}
if(x==3&&y==3) { //最中间的2×2方格中的数字是否等于34
int z=i+a[2][2]+a[2][3]+a[3][2];
if(z!=34) continue;
}
if(x==2&&y==2) { //左上角的数字是否等于34
int z=i+a[1][1]+a[1][2]+a[2][1];
if(z!=34) continue;
}
if(x==2&&y==4) { //右上角的数字是否等于34
int z=i+a[1][3]+a[1][4]+a[2][3];
if(z!=34) continue;
}
if(x==4&&y==2) { //左下角的数字是否等于34
int z=i+a[3][1]+a[3][2]+a[4][1];
if(z!=34) continue;
}
if(x==4&&y==4) { //右下角的数字是否等于34
int z=i+a[3][3]+a[3][4]+a[4][3];
if(z!=34) continue;
}
f[i]=1;//标记
a[x][y]=i;//标记
s(x,y+1);
f[i]=0;//清除标记
}
}
int main() {
cin>>n>>m;
a[n][m]=1;//第n行和第m列的格子放数字1
f[1]=1;//标记1为使用过
s(1,1);//深搜
return 0;
}
洛古原题
~ 搜索+剪枝 ~
此题学好DFS(深搜)和剪枝方面就能直接AC
太水了
注意!!!:剪枝这种算法的时间复杂度是
O(n2n) ^2 ,so 我们要进行优化,不然就会超时。
看起来用"最优性剪枝"不太行,那我们就用”可行性剪枝“来做。
剪枝时要注意点,不要WA了。