【题解】魔板—洛谷P1275。

话说好久没更博了。
最近学了好多知识懒的加进来了。
有幸认识一位大佬。
让我有了继续更博的兴趣。
但这是一个旧的题解。
我在某谷上早就发过的。
拿过来直接用就当回归了吧。


其实这道题有一个特别关键的思路。

拿着你要确定的魔板中列去枚举要匹配的魔板的每一列。

因为列是可以交换的。

而且还有最关键的一个点。

如果你确定了其中有一列对应了,那么你的魔板其实就已经固定了。行就不能变换了。

上边这个关键点的确不好想,但是想通了这个题也就好解决了。

然后就可以用map进行对应开始查询。

如果手里的魔板的数和要确定了一一对应了就YES了。

然后你手里的魔板和需要对应的魔板对应成功就可以输出YES了。

要记着在每次枚举的时候clear一次。

具体看下面代码。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cctype>
#include<map> 
#define rg register
#define int long long 
using namespace std;
inline int read(){
	rg int s=0,f=0;
	rg char ch=getchar();
	while(!isdigit(ch)) f|=(ch=='-'),ch=getchar();
	while(isdigit(ch)) s=(s<<1)+(s<<3)+(ch^48),ch=getchar();
	return f?-s:s;
}
int n,m,k;
const int MAX=115;
int a1[MAX][MAX],a2[MAX][MAX],vis[MAX];
string S;
map<string,int>hsh;
void init(){
	n=read(),m=read();
	for(rg int i=1;i<=n;++i){
		for(rg int j=1;j<=m;++j){
			a1[i][j]=read();
		}
	}
	for(rg int i=1;i<=n;++i){
		for(rg int j=1;j<=m;++j){
			a2[i][j]=read();
		}
	}
}
signed main(){
	k=read();
	++k;
	while(--k){
		bool flag=0;
		init();//初始化。
		for(rg int i=1;i<=m;++i){
			hsh.clear();//每次都要清空。
			for(rg int j=1;j<=n;++j){
				vis[j]=(a1[j][1]==a2[j][i])?0:1;
			}//枚举是否能够对应。
			for(rg int j=1;j<=n;++j){
				for(rg int k=1;k<=m;++k){
					a1[j][k]^=vis[j];
				}
			}//对应就可以^1(代表翻转过了)。
			for(rg int j=1;j<=m;++j){
				string s=S;
				for(rg int k=1;k<=n;++k){
					s+=(char)(a1[k][j]+'0');
				}
				++hsh[s];
			}//转换成字符串。
			for(rg int j=1;j<=n;++j){
				for(rg int k=1;k<=m;++k){
					a1[j][k]^=vis[j];
				}
			}//还原
			for(rg int j=1;j<=m;++j){
				string s=S;
				for(rg int k=1;k<=n;++k){
					s+=(char)(a2[k][j]+'0');
				}
				if(!hsh[s]) break;//这里没被改过就跳过。
				--hsh[s];
				if(j==m) flag=1;
			}
		}
		if(flag) printf("YES\n");
		else printf("NO\n");
	}
	return 0;
}

完美。

posted @ 2019-02-24 19:10  Sinyess  阅读(230)  评论(0编辑  收藏  举报