熄灯问题 BailianPOJ 2811 或者 BailianPOJ 1222
2018-03-28 21:42
260 查看
熄灯问题 BailianPOJ 2811 或者 BailianPOJ 1222
标签(空格分隔): 算法 算法竞赛题目有些长,就不写了,在北大百炼平台上有,1222是英文版题,2811是中文版。这道题我听的郭炜老师的课,做的真心巧妙,用的也是出乎意料。具体解题思路在下面的代码里,是老师的源程序,我手动敲的。其中有很多个地方不好懂,统一分析在代码最后。
#include <memory> #include <string> #include <cstring> #include <iostream> using namespace std; char oriLights[5]; //存放原始输入的灯矩阵,每个字符表示一行 char lights[5]; //变化中的灯的矩阵 char result[5]; //最终的开关结果 int GetBit(char c,int i) //返回某一行的第i个元素,表示灯的开关情况 { return (c >> i)&1; } void SetBit(char &c,int i,int v) //将某盏灯的开关情况改变 { if (v) c|=(1<<i); else c&=~(1<<i); } void FlipBit(char &c,int i) //将某盏灯的明暗情况反转 { c^=(1<<i); } void OutPutResult(int t,char result[]) //输出结果数组 { cout << "PUZZLE #" <<t << endl; for (int i=0;i<5;i++) { for (int j=0;j<6;j++) { cout << GetBit(result[i],j); if (j<5) cout << " "; } cout << endl; } } int main() { int T; cin >> T; for (int t=1;t<=T;t++) { //对每一次测试用例 for (int i=0;i<5;i++) { //对每次用例的每一行 for (int j=0;j<6;j++) { //输入每一个灯的开关情况 int s; cin >> s; SetBit(oriLights[i],j,s); //将输入的灯的情况加入原始数组的比特位 } } for (int n=0;n<64;++n) { //按开关的方式,因为一共6个数,每盏灯有2种状态,则一共有64种状态 int switchs = n; memcpy(lights,oriLights,sizeof(oriLights)); //将原始灯开关数组复制一份到lights,在其中做接下来的操作 for (int i=0;i<5;++i) { //对每一行灯执行操作 result[i]=switchs; //将我们的开关方法输入字符型数据中,以二进制形式存储。等到条件妈满足,作为结果输出 for (int j=0;j<6;j++) { //对每一行上的每一盏灯 if (GetBit(switchs,j)) { //获取这一种操作时,第j位上灯的状况。如果它亮着,就执行下面的模拟,将它“按灭” if (j>0) //j>0,就将它的前一位反转 FlipBit(lights[i],j-1); FlipBit(lights[i],j); //一定会执行的操作,将第j位反转 if (j<5) FlipBit(lights[i],j+1); //j<5,就将它的后一位反转 } } if (i<4) //数组未超限时,对i+1组数组进行操作,表示按了第i行的灯后对i+1行的影响。一个异或就行了,很神奇。 lights[i+1]^=switchs; switchs = lights[i]; //显然,按掉初始时的亮灯后,形成第i行灯亮灭的序列。此时对i行操作已完成,我们要想熄灭第i行剩余灯,就必须在第i+1行按同样位置的灯。 } if (lights[4]==0) { //如果遍历到此处,最后一行的灯都为0,也就是全灭时,就输出result。 OutPutResult(t,result); break; } } } return 0; }
难点:
字符型数据存储布尔值。由于一个字符型数据只占1字节,1字节=8 bit,最大存2^8=256,所以用它可以直接存储少量布尔值数据,正好可以表示这里灯的亮灭。如果将整型数据赋给字符型,字符型的比特位会表示这个整型数的二进制形式。比如下面一段代码,输入一个小于256的正整数,就能输出它在字符型数据中的存储情况。
#include <iostream> #include <algorithm> using namespac 4000 e std; int GetBit(char a,int i); int main() { int n; scanf("%d",&n); char a; a=n; for (int i=7;i>=0;i--) { printf("%d",GetBit(a,i)); if (i!=0) cout << " "; } cout << endl; return 0; } int GetBit(char a,int i) { return (a>>i)&1; }
其中用到了位运算的知识,忘了的只能自行百度了,我也是这样现学的。
2. 位运算。其中数次用到了位运算,用来处理二进制数很方便,很快捷。如果不熟练,最好多做一些习题来巩固一下。
相关文章推荐
- OpenJudge 2811 熄灯问题 / Poj 1222 EXTENDED LIGHTS OUT
- POJ 1222 EXTENDED LIGHTS OUT(熄灯问题——枚举)
- Openjudge 2811 熄灯问题 枚举 爆搜
- poj 1222 熄灯问题
- Openjudge 2811 熄灯问题 枚举 爆搜
- 枚举-OpenJudge-1222-熄灯问题
- OpenJudge百炼-2811-熄灯问题-C语言-枚举
- poj 2811:熄灯问题
- Open Judge 2811 熄灯问题
- Openjudge 2811 熄灯问题 枚举 爆搜
- 2811:熄灯问题 百炼oj
- POJ 2811 熄灯问题
- Openjudge 2811 熄灯问题 枚举 爆搜
- 百练2811:熄灯问题
- Openjudge 2811 熄灯问题 枚举 爆搜
- Openjudge 2811 熄灯问题 枚举 爆搜
- poj1222 熄灯问题
- Openjudge 2811 熄灯问题 枚举 爆搜
- Openjudge 2811 熄灯问题 枚举 爆搜
- POJ 2811 熄灯问题 解题报告