翻纸

Description

给你N张纸牌,一字排开,纸牌有正反面,正面写有0,反面写有1。开始的纸牌可能是一种乱的状态(有0有1)现在你需要整理这些纸牌。但麻烦的是,每当你翻一张纸牌时,他左右两张纸牌也必须跟着翻动,现在给你一个乱的状态,问你能否把他们整理好,使得每张纸牌都正面朝上,如果可以,最少需要多少次操作。

Input

有多组数据,每组数据输入一行01符号串(长度20以内),0表示正面朝上,1表示反面朝上。

Output

对于每组数据,如果可以翻称全都是正面,输出最少需要翻动的次数,否则输出NO。

Sample Input

01
011

Sample Output

NO
1


解题思路:用bfs进行一个一个的搜索,因为串中只有01,所以可以将串转换成十进制,这样就可以产生2^20个不同的数,然后标记数组开2^20这么大即可!

搜索每一个纸牌,当0换1,当1换0,直到都为0结束。这里换的时候需要用与运算,我开始直接换后一直超时。。。换的时候直接对十进制数进行加或减去相应位置的值即可

代码:

#include <iostream>
#include <algorithm>
#include <queue>
#include <math.h>
#include <string.h>
using namespace std;
struct node{
    int lens;
    int steps;
};
int flag,cot;
queue<node>q;
int visit[1100000];
int table[] = {1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,262144,524288,1048576};
int transition(string s)
{
    int figure = 0,point = 0;
    for(int i=s.length()-1;i>=0;i--)
    {
        figure += (s[i] - '0')* table[point++];
    }
    return figure;
}
void fun(struct node * temp,int i)//进行交换
{
    int k = table[i];
    if((temp->lens & k) == 0)//当与为0即为要换成1,所以加
    {
        temp->lens += k;
    }
    else//否则为1即为要换成0,所以减
    {
        temp->lens -= k;
    }
}
void bfs(string s)
{
    while(!q.empty())q.pop();
    int i;
    node s_temp;
    s_temp.steps = 0;
    s_temp.lens = transition(s);
    visit[s_temp.lens] = 1;
    q.push(s_temp);
    int len = s.length();
    while(!q.empty())
    {
        node oper = q.front();
        s_temp = oper;
        flag = 0;
        for(i=0;i<len;i++)
        {
            s_temp = oper;
            fun(&s_temp,i);
            if(i - 1 >= 0)
            {
                fun(&s_temp,i-1);
            }
            if(i + 1 < len)
            {
                fun(&s_temp,i+1);
            }
            s_temp.steps = oper.steps + 1;
            int trans = s_temp.lens;
            if(visit[trans] == 0)
            {
                if(trans == 0)//满足跳出
                {
                    flag = 1;
                    break;
                }
                q.push(s_temp);
                visit[trans] = 1;
            }

        }
        if(flag)
        {
            cot = s_temp.steps;
            break;
        }
        q.pop();
    }
}
int main()
{
    string s;
    while(cin >> s)
    {
        memset(visit,0,sizeof(visit));
        flag = 0;
        cot = 0;
        if(transition(s) == 0)
        {
            cout << "0" <<endl;
            continue;
        }
        bfs(s);
        if(flag)
        {
            cout << cot << endl;
        }
        else
        {
            cout << "NO" << endl;
        }
    }
    return 0;
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值