poj 1222 熄灯问题
–第二次按下同一个按钮时,将抵消第一次按下所产生的效果。
–每个按钮最多只需按一次。
–每个按钮按下的顺序对最后的结果没有影响。
–对第一行每个点亮的灯,只需按下第二行相应的灯,就可以熄
灭第一行所有的灯,那么如此重复下去,第1,2,3,4行的灯都可以熄灭。
位运算解法
//熄灯问题 #include <iostream> #include <cstring> using namespace std; char old[10], lights[10], result[10]; //原数组,灯数组,结果数组 void SetBit(char &c, int i, int v) //c代表第i行的字符,把第i行的第j位设置成v { if(v) { c = c | (1 << i); } else c = c & ~(1 << i); } //v = 1 //如果把第3位上的设置为1 //0010 0101 //0010 0101 | 0000 1000 = 0010 1101 按位或运算 //v = 0 //如果把第2位上的位设置为0 //0010 0101 //~(1 << 2)= ~(0000 0100) = (1111 1011) //0010 0101 & 1111 1011 = 0010 0001 int GetBit(char c, int i) //取出c的第i位上的数字 { return (c >> i) & 1; } //0010 0001 右移3位 0000 0100 & 0000 0001 = 0 void FilpBit(char &c, int i) //翻转c的第i位 { c = c ^ (1 << i); } //0010 0101 //翻转第3位上的数字 //0010 0101 ^ 0000 1000 = 0010 1101 void OutPutResult() { for(int i = 0; i < 5; ++i) for(int j = 0; j < 6; ++j) { cout << GetBit(result[i], j); if(j < 5) cout << " "; else cout << endl; } } int main() { int kase; cin>>kase; for(int i = 1;i <= kase ;i++) { int v, switchs; for(int i = 0; i < 5; ++i) for(int j = 0; j < 6; ++j) { cin >> v; SetBit(old[i], j, v); } for(int n = 0; n < 1 << 6; ++n) { //6个开关,2的6次方种情况, (1 << 6 == 2^6) memcpy(lights, old, sizeof(old)); //还原lights数组 switchs = n; for(int i = 0; i < 5; ++i) { result[i] = switchs; // 0 0 1 0 1 0 for(int j = 0; j < 6; ++j) { if(GetBit(switchs, j)) { if(j > 0) FilpBit(lights[i], j - 1); //翻转左边 FilpBit(lights[i], j); //翻转本身 if(j < 5) FilpBit(lights[i], j + 1); //翻转右边 } } if(i < 4) lights[i + 1] ^= switchs; switchs = lights[i]; } if(lights[4] == 0) { printf("PUZZLE #%d\n",i); OutPutResult(); break; } } } return 0; }
局部替代整体
借鉴某位大佬的 博客
#include<stdio.h> int puzzle[6][8],press[6][8]; bool guess(){ int c,r; for(r=1;r<5;++r){ for(c=1;c<7;++c){ press[r+1][c]=(puzzle[r][c]+press[r][c-1]+press[r][c]+press[r][c+1]+press[r-1][c])%2; }//根据press第一行和puzzle数组计算press的其他值 } for(c=1;c<7;++c){ if((press[5][c-1]+press[5][c]+press[5][c+1]+press[4][c])%2!=puzzle[5][c]) return false; }// return true; } void zhenghe(){//将数据进行整合 int c; bool success; for(c=1;c<7;c++){ press[1][c]=0; } while(guess()==false){//当没有正确答案时,继续下去。找到正确的答案为止 press[1][1]++; c=1; while(press[1][c]>1){ press[1][c]=0; c++; press[1][c]++;//模拟二进制,六位二进制 } } return; } int main(){ int n,i,r,c,a=1; scanf("%d",&n); for(r=0;r<6;++r){ press[r][0]=0; press[r][7]=0; } for(c=1;c<7;++c){ press[0][c]=0; } for(i=0;i<n;++i){ for(r=1;r<6;++r){ for(c=1;c<7;++c){ scanf("%d",&puzzle[r][c]);//输入 } } zhenghe(); printf("PUZZLE #%d\n",a);a++; for(r=1;r<6;++r){ for(c=1;c<7;++c){ printf("%d ",press[r][c]);//输出 } printf("\n"); } } return 0; }
飞行员兄弟 4*4
#include <cstdio> using namespace std; char s[4]; int mp[4][4]; int main() { int arr=0; for(int i=0;i<4; i++) { scanf("%s",s); for(int j=0; j<4; j++) { if(s[j] == '+') { for(int k=0; k<4; k++) { mp[i][k] ++; mp[k][j] ++; } mp[i][j] --; } } } for(int i=0; i<4; i++) { for(int j=0; j<4; j++) { if(mp[i][j] % 2 == 1) arr ++; } } printf("%d\n",arr); for(int i=0; i<4; i++) { for(int j=0; j<4; j++) { if(mp[i][j] % 2 == 1) printf("%d %d\n",i + 1, j + 1); } } return 0; }
翻棋子游戏 poj 1753
#include<cstdio> #include<iostream> #include<cstring> using namespace std; struct node { int x; //用十进制的整数的后16位表示该节点的状态 int steps; //记录到达该节点的步数 int i; //是翻动哪个棋子到达当前的状态,避免返回以前的状态 }; bool vis[100000]={false}; char str[10]; node queue[100000]; void flip(int i,node a,node &b) //i=当前要翻动的棋子编号(0-15),a为queue[p]的形参,b为queue[q]的引用 { int r=i/4,c=i%4; //r、c为当前的要翻动的第i个棋子的行和列坐标 b.x=a.x; //为了不改变前一次记录的状态,先拷贝给b。再来翻棋子,记录新状态。 b.x=b.x^(0x1<<i); //用^0x1取反(0x1表示16进制的1) if(r>0) b.x=b.x^(0x1<<(i-4)); //翻i对应位置上面的棋子 if(r<3) b.x=b.x^(0x1<<(i+4)); //翻i对应位置下面的棋子 if(c>0) b.x=b.x^(0x1<<(i-1)); //翻i对应位置左边的棋子 if(c<3) b.x=b.x^(0x1<<(i+1)); //翻i对应位置右边的棋子 b.i=i; b.steps=a.steps+1; } void init() { queue[0].x=0; //初始化为16进制的0 (10进制和16进制的0是一样的) queue[0].steps=0; queue[0].i=-1; for(int i=0;i<4;i++) { scanf("%s",str); for(int j=0;j<4;j++) { if(str[j]=='b') //黑棋对应的位置置1 (用|0x1置1) queue[0].x=(queue[0].x|(0x1<<i*4+j)); } } } void bfs() { int p=0,q=0; while(!(queue[q].x==0||queue[q].x==0xffff)) //如果不满足全0或者全1的状态 { for(int i=0;i<16;i++) { if(queue[p].i==i) continue; q++; //尾指针后移,为新状态开辟新的记录空间 flip(i,queue[p],queue[q]); if(vis[queue[q].x]) q--; vis[queue[q].x]=true; if(queue[q].x==0||queue[q].x==0xffff) break; } if(p==q) { printf("Impossible\n"); break; } p++; //头指针后移1位,将当前状态作为搜索的初始状态 } if(queue[q].x==0||queue[q].x==0xffff) printf("%d",queue[q].steps); } int main() { init(); bfs(); return 0; }