CSL 的拼图 枚举更新

链接:https://ac.nowcoder.com/acm/contest/551/H
来源:牛客网
 

题目描述

众所周知 CSL 不仅玩魔方很强,打麻将也很强。今天他打魔法麻将的时候,在路上撞到了一个被打乱的 n 维魔法拼图。每一块拼图的位置用一个 n 维的坐标 (p1,p2,…,pn)(p1,p2,…,pn) 来表示。将拼图的任意两块交换位置称为一步。CSL 赶着打魔法麻将时间很紧,对步数和时间也很严格,所以需要用恰好 t 步把拼图复原。请问他能做到吗?

输入描述:

第一行有一个整数 n,表示拼图的维数。

第二行有 n 个整数 d1,d2,…,dnd1,d2,…,dn,分别表示每一维的大小。

下面 2×∏ni=1di2×∏i=1ndi 行,每行有 n 个整数:第 2⋅i−12⋅i−1 行表示 第 i 块拼图的初始位置 (ai,1,ai,2,…,ai,n)(ai,1,ai,2,…,ai,n),第 2⋅i2⋅i 行表示第 i 块拼图的目标位置 (bi,1,bi,2,…,bi,n)(bi,1,bi,2,…,bi,n),保证不会有多个拼图在同一初始位置或目标位置。

最后一行有一个整数 t,表示 CSL 要求的步数。

1≤n≤101≤n≤10
n∏i=1di≤106∏i=1ndi≤106
1≤ai,j,bi,j≤dj1≤ai,j,bi,j≤dj
0≤t≤2⋅1060≤t≤2⋅106

输出描述:

如果 CSL 可以用恰好 t 步复原,在一行输出 "YES",否则输出 "NO"。

示例1

输入

复制

1
1
1
1
1

输出

复制

NO

示例2

输入

复制

2
2 2
1 2
2 1
1 1
2 2
2 1
1 2
2 2
1 1
2

输出

复制

YES

题解:这个题和前面的一个题思路是一样的https://ac.nowcoder.com/acm/contest/551/E,只不过就是哈希处理一下就可以。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define pb push_back
#define mk make_pair
const int N=2e6+10;
map<ll ,int> mp;
int n,m,t;
int a[12],id;
ll b[N],c[N];

int main()
{
	ll x,y;
	m=1;
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
		m*=a[i];
	}

	int ans=0;
	for(int i=1;i<=m;i++)
	{
		x=0;
		for(int j=1;j<=n;j++)
		{
			scanf("%lld",&y);
			x=x*10+y;
		}
		b[i]=x;
		mp[x]=i;
		x=0;
		for(int j=1;j<=n;j++)
		{
			scanf("%lld",&y);
			x=x*10+y;
		}
		c[i]=x;
		
	}
	scanf("%d",&t);
	int pos;
	for(int i=1;i<=m;i++)
	{
		if(b[i]==c[i]) continue;
		ans++;
		pos=mp[c[i]];
	//	cout<<b[i]<<" "<<c[i]<<" "<<pos<<endl;
		mp[b[i]]=pos;
		swap(b[pos],b[i]);
	}
	if(ans<=t && (t-ans)%2==0) cout<<"YES\n";
	else cout<<"NO\n";
	return 0;
}

猜你喜欢

转载自blog.csdn.net/mmk27_word/article/details/88948329