翻纸牌 高校俱乐部 英雄会 csdn

10 篇文章 0 订阅
7 篇文章 0 订阅

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

两星的题目,其实说真的,这题目蛮有意思的,不过贪心算法完美解决。

首先要分支:

人为操作:第一个翻,第一个不翻。(可以同一个空间两次读入,我是开了两个空间……)

之后从i=1开始读起,看i-1是否为1,是的话,就翻动,ans1++,直到len-2,而如果len-1为1,那么ans1=inf

同理对于不人为翻动的执行上数操作,得到ans2.

之后最后的结果就是ans=min(ans1,ans2),如果ans==MAX,那么结果为NO。

来考虑一下,为什么是对的?

在一个翻动的操作中,除了第0位和第len-1位是影响两个,其余均为影响左中右,也就是掀牌的时候,如果看到“中”要翻动,那么“左”本来是好的,则会被干扰,我们可以从为此,我们在保证i步后不需要考虑已经走过的地方,那么我们需要只影响乱序(也就是在左是乱的时候,中就翻)。

其实可以考虑成一个数组

011000101

最后通过加1,直到每一个数都为偶数……要打球了。。晚点再更新。。。

.

/*******************************************************************************/
/* OS           : 3.2.0-58-generic #88-Ubuntu SMP Tue Dec 3 UTC 2013 GNU/Linux
 * Compiler     : g++ (GCC)  4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5)
 * Encoding     : UTF8
 * Date         : 2014-03-18
 * All Rights Reserved by yaolong.
*****************************************************************************/
/* Description: ***************************************************************
*****************************************************************************/
/* Analysis: ******************************************************************
*****************************************************************************/
/*****************************************************************************/



#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define MAX 1<<30
int a[30],b[30];
char str[30];

int main(){
    int i,len,ans,ans1,ans2;
    while(~scanf("%s",str)){
        len=strlen(str);
        for(i=0;i<len;i++){
           a[i]=b[i]=str[i]-'0';
        }
        a[0]=!a[0];
        a[1]=!a[1];
        ans1=1;ans2=0;
        for(i=1;i<len;i++)
        {
            if(a[i-1]){
                ans1++;
                a[i-1]=!a[i-1];
                a[i]=!a[i];
                a[i+1]=!a[i+1];
                }


        }
        if(a[len-1]){ans1=MAX;}

        for(i=1;i<len;i++)
        {
            if(b[i-1]){
                ans2++;
                b[i-1]=!b[i-1];
                b[i]=!b[i];
                b[i+1]=!b[i+1];
                }

        }
        if(b[len-1]){ans2=MAX;}
        ans=ans1>ans2?ans2:ans1;
        if(ans==MAX) printf("NO\n");
        else printf("%d\n",ans);




    };





     return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值