网上上课写的题目 POJ传送们
http://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
正好讨论一下,加深印象。位运算那个我想了很久才转过来弯的。真难想啊
3206

被折叠的 条评论
为什么被折叠?



