题目描述
在奶牛回家休息和娱乐之前,Farmer John 希望它们通过玩游戏获得一些智力上的刺激。游戏板由 n 个相同的孔组成,这些孔最初都是空的。一头母牛要么用石头盖住一个洞,要么揭开一个先前被盖住的洞。游戏状态的定义是哪些洞被石头覆盖,哪些洞没有覆盖。游戏的目标是让奶牛准确地到达每个可能的游戏状态一次,然后返回到所有洞都没有覆盖的状态。以下是他们其中一次游戏的示例(空的洞用 O
表示,用石头盖住的洞用 X
表示):
时间 | 洞 1 | 洞 2 | 洞 3 | 描述 |
---|---|---|---|---|
0 | O | O | O | 一开始所有的洞都是空的 |
1 | O | O | X | 盖上洞 3 |
2 | X | O | X | 盖上洞 1 |
3 | X | O | O | 打开洞 3 |
4 | X | X | O | 盖上洞 2 |
5 | O | X | O | 打开洞 1 |
6 | O | X | X | 盖上洞 3 |
7 | X | X | X | 盖上洞 1 |
现在牛被卡住玩不下去了!他们必须打开一个洞,不管他们打开哪个洞,他们都会到达一个他们已经到达的状态。例如,如果他们从第二个洞中取出岩石,他们将到达他们在时间 2 已经访问过的状态(X O X
)。
下面是一个 3 个孔的有效解决方案:
时间 | 洞 1 | 洞 2 | 洞 3 | 描述 |
---|---|---|---|---|
0 | O | O | O | 一开始所有的洞都是空的 |
1 | O | X | O | 盖上洞 2 |
2 | O | X | X | 盖上洞 3 |
3 | O | O | X | 打开洞 2 |
4 | X | O | X | 盖上洞 1 |
5 | X | X | X | 盖上洞 2 |
6 | X | X | O | 打开洞 3 |
7 | X | O | O | 打开洞 2 |
8 | O | O | O | 打开洞 1,恢复到原来的状态 |
现在,奶牛们厌倦了这个游戏,它们想找你帮忙。
给定 n,求游戏的有效解决方案序列。如果有多个解决方案,则返回任意一个。
输入格式
仅一行,一个整数 n。
输出格式
共 n 行,每行一个长度为 n 的字符串,其中只包含字符 O
和 X
,该行中的第 i 个字符表示第 i 个孔在此状态下是被覆盖还是未覆盖,第一行和最后一行必须全部都是 O
。
输入输出样例
输入 #1复制
3
输出 #1复制
OOO OXO OXX OOX XOX XXX XXO XOO OOO
说明/提示
样例 1 说明
见题目描述。
数据规模与约定
对于 100% 的数据,有 1≤n≤15。
思路:这道题可以用dp来做,我们考虑n为1时的状态为
0
1
我们可以将它翻转后接上
0
1
1
0
然后我们分别在一般的位置加上0和1可得
00
10
11
01
再看n为3时
000
100
110
010
011
111
101
001
所以我们可以得出一种解法:先将n为1的值确定,n为1时有:
0
1
当n>=2时可以先将n-1的结果翻转接上,再在一半的位置分别添加上0和1。
最后一个循环,遇到0就输出‘O’,遇到1就输出‘X’。
记得最后再输出一行‘O‘。
#include <iostream>
#include <math.h>
#include <algorithm>
#include <stack>
#include <string.h>
#include <vector>
#include <cstring>
using namespace std;
int n,tmp=2;
int a[40000][20];//最多有2的15次方行
int main() {
cin>>n;
a[1][1]=0;
a[2][1]=1;
for(int i=2;i<=n;i++)
{
tmp*=2;//翻转后的长度
int y=tmp/2;//记录翻转的位置
for(int j=tmp/2+1;j<=tmp;j++)
{
for(int t=1;t<i;t++)
{
a[j][t]=a[y][t];//翻转
}
y--;
}
for(int j=1;j<=tmp;j++)//在相应的位置添加0和1
{
if(j<=tmp/2)
a[j][i]=0;
else a[j][i]=1;
}
}
for(int i=1;i<=tmp;i++)//结果打印输出
{
for(int j=1;j<=n;j++)
if(a[i][j])cout<<"X";
else
cout<<"O";
cout<<endl;
}
for(int i=1;i<=n;i++)
cout<<"O";
return 0;
}