HDU2209 翻纸牌游戏【技巧】

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=2209

题目大意:

有N张牌,有正面朝上的,也有反面朝上的,现在需要把所有牌都正面朝上,已知每翻一张纸牌,

该纸牌左右两侧各一张纸牌也跟着翻动。现在给你一行只包含字符‘0‘和‘1‘的01字符串,‘1‘代表纸牌

反面,‘0‘代表纸牌正面。现在需要将字符串变为全为"0000…00"的字符串,一次操作只能改变一个

字符本身和它左右两侧各一个字符,问:最少要经过多少次操作,才能使字符串变为"0000…00"。

如果不能翻成"0000…00"的状态,则输出"NO"。

思路:

可以直接想到用广搜来找最小步数。但是观察后发现可以从前到后模拟一下就可以得到结果了。

因为从左向右翻纸牌,对于当前纸牌,只要当前纸牌左侧的纸牌为‘1‘,就不用翻动该纸牌,如果左侧纸

牌为‘0‘,则必须翻动纸牌。而对于第一张纸牌来说,没有左侧纸牌,所以上述判断从第2张纸牌开始,

而第一张纸牌有翻与不翻的两种情况,将这两种情况分别考虑。最后递推到最后一张纸牌,这时,除最

最后一张纸牌外,其余牌都已经变为"0000……0",只需要判断最后一张纸牌是不是‘0‘,就可以知道是不

是能够翻成"0000…00"状态了。如果两者都不能翻成这种状态,则结果输出"NO",否则,输出能翻出的

情况中最小的情况。

AC代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;

char s[22],a[22],b[22];

int Min,Numa,Numb,Num,len,flag;

void solveA()
{
    Num = 0;
    for(int i = 1; i < len; ++i)
    {
        if(a[i-1] == '1')
        {
            a[i-1] = '0';
            if(a[i] == '0')
                a[i] = '1';
            else
                a[i] = '0';
            if(i != len-1)
            {
                if(a[i+1] == '0')
                    a[i+1] = '1';
                else
                    a[i+1] = '0';
            }
            Num++;
        }
    }
    if(a[len-1] == '0')
    {
        Numa = Num;
        flag = 1;
    }
}

void solveB()
{
    Num = 0;
    if(b[0] == '1')
        b[0] = '0';
    else
        b[0] = '1';

    if(b[1] == '1')
        b[1] = '0';
    else
        b[1] = '1';
    Num++;
    for(int i = 1; i < len; ++i)
    {
        if(b[i-1] == '1')
        {
            b[i-1] = '0';

            if(b[i] == '0')
                b[i] = '1';
            else
                b[i] = '0';

            if(i != len-1)
            {
                if(b[i+1] == '0')
                    b[i+1] = '1';
                else
                    b[i+1] = '0';
            }
            Num++;
        }
    }
    if(b[len-1] == '0')
    {
        Numb = Num;
        flag = 1;
    }
}

int main()
{
    while(cin >> s)
    {
        len = strlen(s);
        memset(a,0,sizeof(a));
        memset(b,0,sizeof(b));
        for(int i = 0; i < len; ++i)
            a[i] = b[i] = s[i];
        flag = 0;
        Numa = Numb = 0xffffff0;
        solveA();
        solveB();
        if(len == 1)
        {
            if(s[0] == '1')
                cout << '1' << endl;
            else
                cout << '0' << endl;
            continue;
        }
        if(flag == 0)
            cout << "NO" << endl;
        else
        {
            if(Numa < Numb)
                cout << Numa << endl;
            else
                cout << Numb << endl;
        }
    }

    return 0;
}
时间: 2024-10-23 16:57:12

HDU2209 翻纸牌游戏【技巧】的相关文章

hdu2209翻纸牌游戏(bfs+状态压缩)

Problem Description 有一种纸牌游戏,很有意思,给你N张纸牌,一字排开,纸牌有正反两面,开始的纸牌可能是一种乱的状态(有些朝正,有些朝反),现在你需要整理这些纸牌.但是麻烦的是,每当你翻一张纸牌(由正翻到反,或者有反翻到正)时,他左右两张纸牌(最左边和最右边的纸牌,只会影响附近一张)也必须跟着翻动,现在给你一个乱的状态,问你能否把他们整理好,使得每张纸牌都正面朝上,如果可以,最少需要多少次操作. Input 有多个case,每个case输入一行01符号串(长度不超过20),1表

HDU2209 ( 翻纸牌游戏 )

思路:枚举然后深搜,时间复杂度有点高. 代码: 1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 using namespace std; 6 int a[25]; 7 char c[25]; 8 int flag; 9 int len; 10 int judge() 11 { 12 int i,j; 13 int cnt=0; 14 for

翻纸牌游戏(dfs回溯)

翻纸牌游戏 Time Limit : 9000/3000ms (Java/Other)   Memory Limit : 32768/32768K (Java/Other) Total Submission(s) : 2   Accepted Submission(s) : 2 Problem Description 有一种纸牌游戏,很有意思,给你N张纸牌,一字排开,纸牌有正反两面,开始的纸牌可能是一种乱的状态(有些朝正,有些朝反),现在你需要整理这些纸牌.但是麻烦的是,每当你翻一张纸牌(由正翻

HDU 2209 翻纸牌游戏(dfs)

翻纸牌游戏 Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2180    Accepted Submission(s): 787 Problem Description 有一种纸牌游戏,很有意思,给你N张纸牌,一字排开,纸牌有正反两面,开始的纸牌可能是一种乱的状态(有些朝正,有些朝反),现在你需要整理这些纸牌.但是麻烦的是,每当你翻一张

hdu 2209 翻纸牌游戏

题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=2209 这个题难度还可以 我的思路:有n张牌成第一张牌开始如果是1,则第一张第二张第三张翻转,再看第二张,判断如果是1则第二张第三张第四张翻转,以此下去 不这样还不可以,还得分两种情况如001 按这种思路是不可以的所以还有一种情况不管如何先翻转第一和第二张牌再如上一种思路. 我的AC代码 第一种写法:直接法 #include<cstdio>#include<iostream>#inclu

HDU 2209 翻纸牌游戏(DFS)

题目链接 Problem Description 有一种纸牌游戏,很有意思,给你N张纸牌,一字排开,纸牌有正反两面,开始的纸牌可能是一种乱的状态(有些朝正,有些朝反),现在你需要整理这些纸牌.但是麻烦的是,每当你翻一张纸牌(由正翻到反,或者有反翻到正)时,他左右两张纸牌(最左边和最右边的纸牌,只会影响附近一张)也必须跟着翻动,现在给你一个乱的状态,问你能否把他们整理好,使得每张纸牌都正面朝上,如果可以,最少需要多少次操作. Input 有多个case,每个case输入一行01符号串(长度不超过2

【HDOJ】2209 翻纸牌游戏

状态压缩+双向广搜.注意控制时间t. /* 2209 */ #include <iostream> #include <string> #include <map> #include <queue> #include <set> #include <stack> #include <vector> #include <deque> #include <algorithm> #include <

HDOj-2209-翻纸牌游戏-DFS

翻纸牌游戏 Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2622    Accepted Submission(s): 943 Problem Description 有一种纸牌游戏,很有意思,给你N张纸牌,一字排开,纸牌有正反两面,开始的纸牌可能是一种乱的状态(有些朝正,有些朝反),现在你需要整理这些纸牌.但是麻烦的是,每当你翻一

1647: [Usaco2007 Open]Fliptile 翻格子游戏

1647: [Usaco2007 Open]Fliptile 翻格子游戏 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 423  Solved: 173[Submit][Status][Discuss] Description Farmer John knows that an intellectually satisfied cow is a happy cow who will give more milk. He has arranged a