POJ1753 Flip Game
题目
Description
Flip game is played on a rectangular 4x4 field with two-sided pieces placed on each of its 16 squares. One side of each piece is white and the other one is black and each piece is lying either it's black or white side up. Each round you flip 3 to 5 pieces, thus changing the color of their upper side from black to white and vice versa. The pieces to be flipped are chosen every round according to the following rules:
- Choose any one of the 16 pieces.
- Flip the chosen piece and also all adjacent pieces to the left, to the right, to the top, and to the bottom of the chosen piece (if there are any).
Consider the following position as an example:
bwbw wwww bbwb bwwb
Here "b" denotes pieces lying their black side up and "w" denotes pieces lying their white side up. If we choose to flip the 1st piece from the 3rd row (this choice is shown at the picture), then the field will become:
bwbw bwww wwwb wwwb
The goal of the game is to flip either all pieces white side up or all pieces black side up. You are to write a program that will search for the minimum number of rounds needed to achieve this goal.
Input
The input consists of 4 lines with 4 characters "w" or "b" each that denote game field position.
Output
Write to the output file a single integer number - the minimum number of rounds needed to achieve the goal of the game from the given position. If the goal is initially achieved, then write 0. If it's impossible to achieve the goal, then write the word "Impossible" (without quotes).
Sample Input
bwwb bbwb bwwb bwww
Sample Output
4
Source
题解
知识点:枚举,状压,递推。
首先注意到可以通过对第 行操作第 行全部按灭或按亮,于是可以通过这个操作将状态变换成最后一行的亮灭,而前三行统一亮灭。而基于这些操作的最后一行如果不是全灭或全亮就说明初状态不可行,否则可行。
然后,对于第一行会有 种初状态,只要遍历这些状态,分别执行上述操作即可。
具体操作上,可以用一个 位二进制 表示对 行灯的开关操作, 表示按, 表示不按。对于 行的状态 而言,需要将 的位置取反且周围 个也取反, 的位置不变,即 ;对于 行的状态 而言,即 ,观察这个性质,我们可以将下一次按钮方式设置为本行的灯状态,做到用下一行按本行的灯;对于 行的状态 而言,即 。需要注意 可能在int里面使范围外的二进制码改变需要加上限制 ,其中 。
最后计算 的二进制位为 的位数更替最小值,利用性质 可以消去二进制最后一位 来计数。
时间复杂度
空间复杂度
本题可变种为 行 列的矩阵,利用同样方法即可,查看NC235250。
时间复杂度
空间复杂度
代码
#include <iostream> using namespace std; const int n = 4,m = 4; int a[n+7],b[n+7]; int change[n+7]; int calc(int num){ int cnt = 0; while(num){ cnt++; num &= num-1; } return cnt; }///计算二进制有几个1 int deal(int a[]){ int cur[n+7],ans = ~(1<<31),cnt = 0; for(change[0] = 0;change[0]<(1<<m);change[0]++){ cnt = calc(change[0]); cur[0] = a[0] ^ change[0] ^ (change[0]>>1) ^ ((change[0]<<1) & ((1<<m)-1));///最后一个保证不改变int的其他位,改变的话计数会错误 cur[1] = a[1] ^ change[0]; for(int i = 1;i<n;i++){ change[i] = cur[i-1]; cnt += calc(change[i]); cur[i] = cur[i] ^ change[i] ^ (change[i]>>1) ^ ((change[i]<<1) & ((1<<m)-1));///是用cur[i]现在的i行,不是a[i]原来的i行,因为原来的已经被上一行改变 cur[i+1] = a[i+1] ^ change[i];///对原来的行进行操作 } if(!cur[n-1]){ ans = min(ans,cnt); } } return ans; } int main(){ for(int i = 0;i<n;i++){ for(int j = 0;j<n;j++){ char tmp; cin>>tmp; if(tmp == 'w') a[i] |= (1<<j); else if(tmp == 'b') b[i] |= (1<<j); } } int ans = min(deal(a),deal(b)); if(ans>n*m) cout<<"Impossible"<<'\n'; else cout<<ans<<'\n'; return 0; }
本文来自博客园,作者:空白菌,转载请注明原文链接:https://www.cnblogs.com/BlankYang/p/16250506.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧