隐藏
「bsoj3363」魔板 - 搜索 | Bill Yang's Blog

路终会有尽头,但视野总能看到更远的地方。

0%

「bsoj3363」魔板 - 搜索

题目大意

有这样一种魔板:它是一个长方形的面板,被划分成$n$行$m$列的$n*m$个方格。每个方格内有一个小灯泡,灯泡的状态有两种(亮或暗)。我们可以通过若干操作使魔板从一个状态改变为另一个状态。操作的方式有两种:
(1)任选一行,改变该行中所有灯泡的状态,即亮的变暗、暗的变亮;
(2)任选两列,交换其位置。
当然并不是任意的两种状态都可以通过若干操作来实现互相转化的。
你的任务就是根据给定两个魔板状态,判断两个状态能否互相转化。


题目分析

第一眼可以上一个简单的Bfs,然后发现状态量有点大。

因为变换是在行中进行的,因此无论如何变换,一行中$0/1$的数目只会发生交换而不会变化。

不妨枚举结束状态$ed$的第一列是由起始状态$st$哪一列交换而来,那么任意行改变$0/1$的方案就唯一确定了。

接下来再任意交换检查其能否到达$ed$状态即可。


代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#include<algorithm>
#include<iostream>
#include<iomanip>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<cmath>
#include<queue>
using namespace std;
inline const int Get_Int() {
int num=0,bj=1;
char x=getchar();
while(x<'0'||x>'9') {
if(x=='-')bj=-1;
x=getchar();
}
while(x>='0'&&x<='9') {
num=num*10+x-'0';
x=getchar();
}
return num*bj;
}
int n,m;
struct State {
bool a[105][105];
bool* operator [] (const int& x) {
return a[x];
}
void row(int x) {
for(int i=1; i<=m; i++)a[x][i]=!a[x][i];
}
void line(int x,int y) {
for(int i=1; i<=n; i++)swap(a[i][x],a[i][y]);
}
} st,ed;
bool Same(State a,int x,State b,int y) {
for(int i=1; i<=n; i++)
if(a[i][x]!=b[i][y])return false;
return true;
}
int t;
int main() {
t=Get_Int();
while(t--) {
n=Get_Int();
m=Get_Int();
for(int i=1; i<=n; i++)
for(int j=1; j<=m; j++)
st[i][j]=Get_Int();
for(int i=1; i<=n; i++)
for(int j=1; j<=m; j++)
ed[i][j]=Get_Int();
bool bj=0;
for(int k=1; k<=m; k++) { //第一列从第k列交换而来
State tmp=st;
tmp.line(1,k);
for(int i=1; i<=n; i++)
if(tmp[i][1]!=ed[i][1])tmp.row(i);
for(int i=1; i<=m; i++) {
bj=0;
for(int j=i; j<=m; j++)
if(Same(tmp,j,ed,i)) {
tmp.line(i,j);
bj=1;
break;
}
if(!bj)break;
}
if(bj)break;
}
if(bj)puts("YES");
else puts("NO");
}
return 0;
}
姥爷们赏瓶冰阔落吧~