P6183 [USACO10MAR] The Rock Game S

  • Post author:
  • Post category:其他


在奶牛回家休息和娱乐之前,Farmer John 希望它们通过玩游戏获得一些智力上的刺激。游戏板由 nn 个相同的孔组成,这些孔最初

都是空的

。一头母牛要么用石头盖住一个洞,要么揭开一个先前被盖住的洞。

游戏状态

的定义是哪些洞被石头覆盖,哪些洞没有覆盖。游戏的目标是让奶牛准确地到达每个可能的游戏状态一次,然后返回到所有洞都没有覆盖的状态。以下是他们其中一次游戏的示例(空的洞用

O

表示,用石头盖住的洞用

X

表示):

时间 洞 1 洞 2 洞 3 描述
00 O O O 一开始所有的洞都是空的
11 O O X 盖上洞 3
22 X O X 盖上洞 1
33 X O O 打开洞 3
44 X X O 盖上洞 2
55 O X O 打开洞 1
66 O X X 盖上洞 3
77 X X X 盖上洞 1

现在牛被卡住玩不下去了!他们必须打开一个洞,不管他们打开哪个洞,他们都会到达一个他们已经到达的状态。例如,如果他们从第二个洞中取出岩石,他们将到达他们在时间 22 已经访问过的状态(

X O X

)。

下面是一个 3 个孔的有效解决方案:

时间 洞 1 洞 2 洞 3 描述
00 O O O 一开始所有的洞都是空的
11 O X O 盖上洞 2
22 O X X 盖上洞 3
33 O O X 打开洞 2
44 X O X 盖上洞 1
55 X X X 盖上洞 2
66 X X O 打开洞 3
77 X O O 打开洞 2
88 O O O 打开洞 1,恢复到原来的状态

现在,奶牛们厌倦了这个游戏,它们想找你帮忙。

给定 nn,求游戏的有效解决方案序列。如果有多个解决方案,则返回

任意一个

输入格式

仅一行,一个整数 nn。

输出格式

共 2^n+12n+1 行,每行一个长度为 nn 的字符串,其中只包含字符

O



X

,该行中的第 ii 个字符表示第 ii 个孔在此状态下是被覆盖还是未覆盖,第一行和最后一行必须全部都是

O

输入输出样例


输入 #1

复制

3


输出 #1

复制

OOO
OXO
OXX
OOX
XOX
XXX
XXO
XOO
OOO

思路:如果去掉两个全都是0的序列的话就是有2^n-1个序列

状态用1~2^n的二进制数表示

然后我们就找1~2^n的全排列中满足相邻的两个数相差一位的序列

用一个数来记录一下,找到了就更改一下,每次递归首先判断一下是否已经更改,如果更改了就直接返回

用一个数组来记录2^n-1个状态的方案序列

然后每次递归记录的是当前搜到第几个状态,如果搜到了最后的先输出全是0再输出序列再输出全是0

因为我们要找的是1~2^n的二进制表示的状态,为了避免搜到0我们先把0标记为已经用过

然后我们开始从第一个序列递归

设每次递归到第u个状态的数,那我们就一位一位看第u-1个状态的数

如果第i位的数是1就减掉第i位的1递归,如果是0就加上第i位上的1递归

具体见代码注释


/*

 .----------------.  .----------------.  .----------------.  .----------------. 
| .--------------. || .--------------. || .--------------. || .--------------. |
| |  ________    | || |  _________   | || | ____    ____ | || |     ____     | |
| | |_   ___ `.  | || | |_   ___  |  | || ||_   \  /   _|| || |   .'    `.   | |
| |   | |   `. \ | || |   | |_  \_|  | || |  |   \/   |  | || |  /  .--.  \  | |
| |   | |    | | | || |   |  _|  _   | || |  | |\  /| |  | || |  | |    | |  | |
| |  _| |___.' / | || |  _| |___/ |  | || | _| |_\/_| |_ | || |  \  `--'  /  | |
| | |________.'  | || | |_________|  | || ||_____||_____|| || |   `.____.'   | |
| |              | || |              | || |              | || |              | |
| '--------------' || '--------------' || '--------------' || '--------------' |
 '----------------'  '----------------'  '----------------'  '----------------'

*/
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<deque>
#include<cmath>
#include<stack>
#define int long long
#define lowbit(x) x&(-x)
#define PI 3.1415926535
#define endl "\n"
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
int gcd(int a,int b) {
	return b? gcd(b,a%b):a;
}
/*
int dx[8]={-2,-2,-1,1,2,2,-1,1};
int dy[8]={-1,1,2,2,1,-1,-2,-2};
int dx[4]={0,-1,0,1};
int dy[4]={-1,0,1,0};
int dx[8]={-1,1,0,0,-1,-1,1,1};
int dy[8]={0,0,-1,1,-1,1,-1,1};
*/
//int e[N],ne[N],h[N],idx,w[N];
/*void add(int a,int b,int c){
	e[idx]=b;
	w[idx]=c;
	ne[idx]=h[a];
	h[a]=idx++;
}
*/
const int N=1<<15+5;
int m,f,n;
int c[N];//记录每个状态是否出来过
int a[N];
void dfs(int u){//记录当前状态的下标
    if(f)return ;
	if(u==m){
		f=1;
		for(int i=0;i<n;i++)cout<<"O";
		cout<<endl;
		for(int i=1;i<m;i++){
			for(int j=0;j<n;j++){
				if((a[i]>>j)&1)cout<<"X";
				else cout<<"O";
			}
			cout<<endl;
		}
		for(int i=0;i<n;i++)cout<<"O";
		cout<<endl;		
		return ;
	}
	int now;
	for(int i=0;i<n;i++){
		if((a[u-1]>>i)&1){
			now=a[u-1]-(1<<i);
		}else now=a[u-1]+(1<<i);
		if(!c[now]){//如果没被用过
			c[now]=1;//标记一下
			a[u]=now;//现在这个状态是now
			dfs(u+1);//递归下一位
			c[now]=0;//如果找不到正确答案那就回溯
			a[u]=0;
		}
	}
	return ;
}
void sove(){
	cin>>n;
	m=1<<n;
	c[0]=1;
	dfs(1);
}

signed main(){
	sove();

	return 0;
}



版权声明:本文为qq_61903556原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。