洛谷----P6183 [USACO10MAR] The Rock Game S

题目描述

在奶牛回家休息和娱乐之前,Farmer John 希望它们通过玩游戏获得一些智力上的刺激。游戏板由 n 个相同的孔组成,这些孔最初都是空的。一头母牛要么用石头盖住一个洞,要么揭开一个先前被盖住的洞。游戏状态的定义是哪些洞被石头覆盖,哪些洞没有覆盖。游戏的目标是让奶牛准确地到达每个可能的游戏状态一次,然后返回到所有洞都没有覆盖的状态。以下是他们其中一次游戏的示例(空的洞用 O 表示,用石头盖住的洞用 X 表示):

时间洞 1洞 2洞 3描述
0OOO一开始所有的洞都是空的
1OOX盖上洞 3
2XOX盖上洞 1
3XOO打开洞 3
4XXO盖上洞 2
5OXO打开洞 1
6OXX盖上洞 3
7XXX盖上洞 1

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

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

时间洞 1洞 2洞 3描述
0OOO一开始所有的洞都是空的
1OXO盖上洞 2
2OXX盖上洞 3
3OOX打开洞 2
4XOX盖上洞 1
5XXX盖上洞 2
6XXO打开洞 3
7XOO打开洞 2
8OOO打开洞 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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值