NC106350 POJ1753 Flip Game 翻转游戏

网上上课写的题目  POJ传送们icon-default.png?t=M85Bhttp://poj.org/problem?id=1753

 先贴代码,感觉里面重点部分说的已经比较清楚了

#include <iostream>
#include <stdlib.h>
#include <algorithm>
using namespace std;
const int n = 4, m = 4;
int a[m + 10], b[m + 10];
int change[n + 10]; //灯泡需要做出的变化
/*
bwwb
bbwb
bwwb
bwww
*/

int clac(int x)
{
    int cent = 0;
    while (x)
    {
        if ((x & 1))
            cent++;
        x >>= 1;
    }
    return cent;
}
int deal(int a[])
{
    int ans = 0x7f7f7f7f;
    int cur[n + 10], cnt = 0; //新定义一个暂时数组用来保存灯泡当前的亮灭情况
    for (change[0] = 0; change[0] <= ((1 << m) - 1); change[0]++)
    {
        cnt = clac(change[0]);
        //第一排灯泡一共有15种不同的变化,用0  1 数列来表示这种变化
        //我们首先要去确定每一种第一排变化所带来后面几排的变化
        //因为我们对第一排的操作是能影响第二排的,而第二排的change 操作与上一排(按完之后) 的0  1 情况一样
        cur[0] = a[0] ^ change[0] ^ (change[0] >> 1) ^ ((change[0] << 1) & ((1 << m) - 1));
        //((change[0]<<1)&(1<<m)-1) 是指如果change 左移一位 那么就会会出现第五位数
        //比如:1010 左移一位——> 10100 但我们只需要0100 这个序列
        //所以就要对 **(1<<m)-1 == 1111 ** 这个数进行 与 运算(只有同为 1 的时候才为 1 )
        cur[1] = a[1] ^ change[0];
        for (int i = 1; i < n; i++)
        {
            change[i] = cur[i - 1];
            cnt += clac(change[i]); //统计change 中 1 出现的次数,就是按了几次
            cur[i] = cur[i] ^ change[i] ^ (change[i] >> 1) ^ ((change[i] << 1) & (1 << m) - 1);
            cur[i + 1] = a[i + 1] ^ change[i];
        }
        if (cur[n - 1] == 0)
            ans = min(ans, cnt);
    }
    return ans;
}

int main()
{
    for (int i = 0; i < 4; i++)
        for (int j = 0; j < 4; j++)
        {
            char c;
            scanf(" %c", &c);
            if (c == 'b')
                a[i] |= (1 << j);
            else
                b[i] |= (1 << j);
        }
    int ans = min(deal(a), deal(b));
    if (ans > n * m)
        cout << "Impossible" << endl;
    else
        cout << ans;

    system("pause");
}


首先让我们理清一下思路。

问题:怎么样才能让所有的都变白或者都变黑

因为变白和变黑的两种状态,所以我们可以用 0 1 这种二进制位运算去解决这个问题

(因为我也是才学的,所以感觉像这种2种状态的题都可以根据这种 0 1 位运算思路去解决)

下面就是比较难理解的了,我们首先让他全变亮为主要目标

我们会有一个简单的思路,就是一排一排的去让它全变亮,

第一排我们一共有 2的4次方-1 种按法 根据第一排的不同按法,然后第二排相应给出对应的按法,

然后不断循环,直到最后一排。这时候前几排都是已经变亮的,这时候,我们会发现,如果最后一排不是都亮的,那么这种方式就是无解的。

所以推出第一排的按法有问题,从而不断循环,

那发生错误,所有都不满足的条件是什么呢:就是按遍了都没按出来。这样就返回impossible

 

其实只有第一排的选项会影响下面的选择,

我们只用遍历出第一排所有的情况,根据固定的方式就能去推出下面的情况

最终确定有没有灯还在亮着。

为了把零 0 排按灭,我们会发现,第 1 排按灭的方式与第 0 排亮着的方式一样

所以我们能通过第一排按的方式知道下一排按的方式。以此循环

最终确定。

简单记录一下我写过程的一些思路,如果想详细了解的可以加我QQ:2268568923

正好讨论一下,加深印象。位运算那个我想了很久才转过来弯的。真难想啊

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值