题目背景
为了揭开月光能量背后的秘密,你来到了地下的远古档案馆。
远古一族的秘密与遗忘的知识悉数贮藏于这片被尘封的迷宫中,你能成功解谜,获知远古的知识吗?
题目描述
远古档案馆的中心是一个解谜:
-
有一个 2\times 22×2 的网格,每个格子中要么有一个正整数,要么是空的;
-
你可以进行若干次操作:每次操作中,你选择一个有正整数的格子和一个与之相邻的空格子,将正整数移到那个空格子中;
-
给定网格的初始状态和最终状态,保证初始状态和最终状态中包含的正整数个数相同(设为 kk 个),且它们就是前 kk 个不同的正整数,问是否可以通过有限次操作从初始状态到达最终状态?
下图展示了一个包含三个正整数的网格经过两次操作的情况:
只有完成解谜,才能获得遗忘的知识,因此你希望尽快解决这个问题。
注意:网格中可能没有正整数,也可能没有空格。
输入格式
输入共包括四行,每行两个整数。
前两行描述了初始状态,后两行描述了最终状态,用 00 表示空格子。
输出格式
如果可以从初始状态到达最终状态,输出 Yes
,否则输出 No
。
输入输出样例
输入 #1复制
2 1 3 0 0 2 3 1
输出 #1复制
Yes
输入 #2复制
2 1 4 3 3 4 2 1
输出 #2复制
No
说明/提示
【样例 1 解释】
如题目描述中图所示。
【样例 2 解释】
没有可移动的正整数,所以无法从初始状态到达与之不相等的最终状态。
【数据范围】
本题采用捆绑测试。
所有数据符合题目描述所述。
- Subtask 1(40 points):不存在空格。
- Subtask 2(60 points):无特殊限制。
上代码:
#include<iostream>
#include<cstdio>
using namespace std;
int a[5],b[5],num=0,k;
bool judge1(){
if(a[1]==b[3]&&a[2]==b[4]){ //a的第一行与b的第二行相同
if(a[1]!=0&&a[2]!=0) return 1;
}
if(a[3]==b[1]&&a[4]==b[2]){ //a的第二行与b的第一行相同
if(a[3]!=0&&a[4]!=0) return 1;
}
if(a[1]==b[2]&&a[3]==b[4]){ //a的第一列与b的第二列相同
if(a[1]!=0&&a[3]!=0) return 1;
}
if(a[2]==b[1]&&a[4]==b[3]){ //a的第二列与b的第一列相同
if(a[2]!=0&&a[4]!=0) return 1;
}
return 0;
}
bool judge2(){
if(a[1]==b[1]&&a[2]==b[2]){ //a的第一行与b的第一行相同
if(a[1]==0||a[2]==0) return 1;
}
if(a[3]==b[3]&&a[4]==b[4]){ //a的第二行与b的第二行相同
if(a[3]==0||a[4]==0) return 1;
}
if(a[1]==b[1]&&a[3]==b[3]){ //a的第一列与b的第一列相同
if(a[1]==0||a[3]==0) return 1;
}
if(a[2]==b[2]&&a[4]==b[4]){ //a的第二列与b的第二列相同
if(a[2]==0||a[4]==0) return 1;
}
return 0;
}
bool judge3(){
if(a[1]==b[1]&&a[4]==b[4]|| //a,b左上与右下相同
a[2]==b[2]&&a[3]==b[3]){ //a,b右上与左下相同
return 1;
}
return 0;
}
bool same(){ //a,b四个格完全相同
if(a[1]==b[1]&&a[2]==b[2]&&a[3]==b[3]&&a[4]==b[4]) return 1;
return 0;
}
bool move(int x){
swap(a[k],a[x]); //x格中数字移到空格位置
if((judge1()||judge2()||judge3())&&!same()) return 1;
else swap(a[k],a[x]); //判断不成立,数字回到x格
return 0;
}
int main(){
scanf("%d %d %d %d",&a[1],&a[2],&a[3],&a[4]);
scanf("%d %d %d %d",&b[1],&b[2],&b[3],&b[4]);
for(int i=1;i<=4;i++){
if(a[i]==0){
num++; //记录空格个数
k=i; //记录空格出现位置
}
}
if(same()){ //四个格全部相同
printf("Yes");
return 0;
}
if(num==0){ //四个格全部不为空
printf("No");
return 0;
}
if(num>=2){ //空格个数两个及以上
printf("Yes");
return 0;
}
//以下均为只存在一个空格的情况
if(judge1()||judge2()||judge3()){ //判断
printf("No");
return 0;
}
if(k==2||k==3){ //空格位置为2或3时
if(move(1)||move(4)){ //判断1,4格中数字移到空格位置时
printf("No");
return 0;
}
}
if(k==1||k==4){ //空格位置为1或4时
if(move(2)||move(3)){ //判断2,3格中数字移到空格位置时
printf("No");
return 0;
}
}
printf("Yes"); //全部不成立,结束
return 0;
}