P1274 魔术数字游戏(DFS)

题目描述

填数字方格的游戏有很多种变化,如下图所示的 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=14 j = 1 ⋯ 4 j=1 \cdots 4 j=14)。为了让游戏更有挑战性,我们要求下列六项中的每一项所指定的四个格子,其数字累加的和必须为 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=14
- 每条垂直线上四个格子中的数字,即 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=14
- 两条对角线上四个格子中的数字,例如左上角到右下角 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 1i,j4

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) ^2so 我们要进行优化,不然就会超时
看起来用"最优性剪枝"不太行,那我们就用”可行性剪枝“来做。
剪枝时要注意点,不要WA了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值