poj1753 Flip Game
题意:4*4的正方形,每个格子有黑白两面,翻转格子使得4*4个格子显示全黑或全白,翻转要求:选中的那个格子,以及其上下左右相邻的格子(如果存在)要同时翻转。输出最小的达到要求的翻转次数或者Impossible(如果不可能)
题目链接:http://poj.org/problem?id=1753
分析:因为每个格子只有黑白两面,所以对于每个格子来说,要么不翻转,要么翻转一次,因为翻转奇数次结果和翻转一次得到的效果是一样的,而翻转偶数次得到的效果和不翻转是一样的,则总共有16个格子,最多要翻转16次,每个格子有黑白两种颜色,假设每一次面临的4*4正方形代表一个状态,则总共有2^16种状态,可以用16位二进制数表示,每一位1代表'b'(白),0代表'w'(黑)。当状态为(0或者65535)时则达到要求。
注意:1.因为只用求最少次数,用bfs做,将每一个没有访问到的状态 (用vis[]数组标记) 加入到队列中,如果游戏无法完成,状态必定会形成循环,由于重复状态不会再次入队,所以最后的队列一定会是空队列。当队列为空时说明此时还未达到要求,则是Impossible
2.二进制运算,翻转某一个格子即指将1变成0,0变成1.这里可以用异或运算的性质,1^0=1,0^0=0;所以只用将需要翻转的那个格子对应的16位二进制数的位置为1,其他不翻转的格子对应的16位二进制数的位置为0得到一个数和当前状态的16位二进制数异或即可得到翻转后的状态。
例如:
bwwb
bbwb
bwwb
bwww
的状态可以表示为1001 1101 1001 1000 (二进制),如果我现在要翻转第一行第一个格子,则可以用此二进制数和1100 1000 0000 0000 异或,则可以得到下一个状态next=1001 1101 1001 1000 ^ 1100 1000 0000 0000 = 0101 0101 1001 1000
即:
wbwb
wbwb
bwwb
bwww
可以得到转换每一个格子需要异或的二进制数(十进制表示):
int change[16] = {
51200,58368,29184,12544,
35968,20032,10016,4880,
2248,1252,626,305,
140,78,39,19
};
代码:
int dir[][]={{,},{-,},{,},{,-}};
void init()
{
int i,j,x,y,t,temp;
for(i=;i<;++i)
{
for(j=;j<;++j)
{
temp = ;
temp ^= (<<( - ( i* + j )));
for(t=;t<;++t)
{
x = i + dir[t][];
y = j + dir[t][];
if(x< || y< || x> || y>)
continue;
temp ^= (<<((-x)*+-y));
}
cout<<temp<<" ";
}
cout<<endl;
}
}
完整代码1:(bfs+bit)
#include<iostream>
#include<cstdio>
#include<queue>
#include<cmath>
#include<string>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
char m[][];
//int di[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
struct Node
{
int state,step;
}nod[];
int vis[];
/*
int change[16] = //16种状态转换,对应4*4的翻子位置 方法2.直接异或得到状态
{
51200,58368,29184,12544,
35968,20032,10016,4880,
2248,1252,626,305,
140,78,39,19
};
*/
int getChang(int stat,int x,int y) //方法1.翻转需要翻转的格子
{
int tp=stat;
tp^=(<<(-x*-y));
if(x>) tp^=(<<(-(x-)*-y)); //上
if(x<) tp^=(<<(-(x+)*-y)); //下
if(y>) tp^=(<<(-x*-y+)); //左
if(y<) tp^=(<<(-x*-y-)); //右
return tp;
}
int bfs(Node cur)
{
queue<Node>q;
q.push(cur);
Node next;
vis[cur.state]=; while(!q.empty())
{
cur=q.front();
q.pop();
if(cur.state==||cur.state==) //判断是否全黑/全白
return cur.step;
for(int i=;i<;i++)
{
for(int j=;j<;j++)
{
next.state=getChang(cur.state,i,j); //按部得到状态
//next.state=cur.state^change[i]; //直接异或得到状态 (循环要改为for(int i=0;i<16;i++) )
next.step=cur.step+;
if(next.state==||next.state==)
return next.step;
if(vis[next.state]) //是否已经入队过
continue;
q.push(next);
vis[next.state]=;
}
}
}
return -;
}
int main()
{
memset(vis,,sizeof(vis));
int tmp=;
for(int i=;i<;i++)
{
cin>>m[i];
for(int j=;j<;j++)
{
if(m[i][j]=='b')
tmp+=(<<(-*i-j));
}
}
Node cur;
cur.state=tmp;
cur.step=;
int ans=bfs(cur);
if(ans==-)
printf("Impossible\n");
else
printf("%d\n",ans);
return ;
}
完整代码2:(dfs)
#include<iostream>
#include<cstdio>
#include<cmath>
#include<queue>
#include<vector>
#include<map>
#include<algorithm>
#include<string>
#include<cstring>
using namespace std;
int mp[][];
int step;
bool flag;
int judge()
{
for(int i=;i<;i++)
for(int j=;j<;j++)
if(mp[i][j]!=mp[][])
return ;
return ;
}
void flip(int x,int y)
{
mp[x][y]=!mp[x][y];
if(x>) mp[x-][y]=!mp[x-][y];
if(x<) mp[x+][y]=!mp[x+][y];
if(y>) mp[x][y-]=!mp[x][y-];
if(y<) mp[x][y+]=!mp[x][y+];
}
void dfs(int x,int y,int deep)
{
if(deep==step)
{
flag=judge();
return;
}
if(flag||x>=)
return;
flip(x,y);
if(y<)
dfs(x,y+,deep+);
else
dfs(x+,,deep+);
flip(x,y);
if(y%<)
dfs(x,y+,deep);
else
dfs(x+,,deep);
return;
}
int main()
{
string s;
flag=;
for(int i=;i<;i++)
{
cin>>s;
for(int j=;j<;j++)
if(s[j]=='b')
mp[i][j]=;
}
for(step=;step<=;step++)
{
dfs(,,);
if(flag)
break;
}
if(flag)
printf("%d\n",step);
else
printf("Impossible\n");
return ;
}
poj1753 Flip Game的更多相关文章
- poj1753 Flip Game(BFS+位压缩)
题目链接 http://poj.org/problem?id=1753 题意 一个棋盘上有16个格子,按4×4排列,每个格子有两面,两面的颜色分别为黑色和白色,游戏的每一轮选择一个格子翻动,翻动该格子 ...
- poj1753,Flip Game,ArrayDeque<Node>
Flip Game Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 30449 Accepted: 13232 Descr ...
- POJ1753 Flip Game(bfs、枚举)
链接:http://poj.org/problem?id=1753 Flip Game Description Flip game is played on a rectangular 4x4 fie ...
- POJ1753——Flip Game
Flip Game Description Flip game is played on a rectangular 4x4 field with two-sided pieces placed on ...
- POJ-1753 Flip Game---二进制枚举子集
题目链接: https://vjudge.net/problem/POJ-1753 题目大意: 有4*4的正方形,每个格子要么是黑色,要么是白色,当把一个格子的颜色改变(黑->白或者白-> ...
- POJ-1753 Flip Game (BFS+状态压缩)
Description Flip game is played on a rectangular 4x4 field with two-sided pieces placed on each of i ...
- POJ1753 Flip Game(位运算+暴力枚举)
Flip game is played on a rectangular 4x4 field with two-sided pieces placed on each of its 16 square ...
- poj1753 Flip Game —— 二进制压缩 + dfs / bfs or 递推
题目链接:http://poj.org/problem?id=1753 Flip Game Time Limit: 1000MS Memory Limit: 65536K Total Submis ...
- [POJ1753]Flip Game(异或方程组,高斯消元,枚举自由变量)
题目链接:http://poj.org/problem?id=1753 题意:同上. 这回翻来翻去要考虑自由变元了,假设返回了自由变元数量,则需要枚举自由变元. /* ━━━━━┒ギリギリ♂ eye! ...
随机推荐
- SQL SERVER 数据库备份的三种策略及语句
1.全量数据备份 备份整个数据库,恢复时恢复所有.优点是简单,缺点是数据量太大,非常耗时 全数据库备份因为容易实施,被许多系统优先采用.在一天或一周中预定的时间进行全数据库备份使你不用动什么脑筋 ...
- 不安装oracle客户端,用plsql连接oracle
常用的Oracle开发的工具有SQL Developer和PL/SQL Developer,个人感觉前者虽然跨平台性优于后者,但比较大(大于300M)占用资源,而且用户体验也一般,而后者相对就小很多( ...
- 关于el jstl
requestScope表示从request范围内取得.其他的还有sessionScope, pageScope和applicationScope,分别对应4种属性范围.而如果直接写${passwor ...
- Android 启动多个闹钟。
Intent i=new Intent(TimeSetActivity.this,AlarmReceiver.class); PendingIntent pi = PendingIntent.getB ...
- LA 5713 秦始皇修路 MST
题目链接:http://vjudge.net/contest/144221#problem/A 题意: 秦朝有n个城市,需要修建一些道路使得任意两个城市之间都可以连通.道士徐福声称他可以用法术修路,不 ...
- libevent源码分析:event_assign、event_new
在libevent中,获取event类型对象的方法有两种,event_assign.event_new 1.event_assign() /** Prepare a new, already-allo ...
- dynamic与匿名对象
用dynamic接收匿名对象很方便,因为不需要去定义model了,但是也有一个弊端,就是匿名对象的作用范围是internal的,也就是只能存在于当前程序域,所以用dynimic跨程序域去接收一个匿名对 ...
- 查看/关闭SElinux (原创帖,转载请注明出处)
查看SELinux状态: 1 /usr/sbin/sestatus -v | grep "SELinux status:" ##如果SELinux status参数为enabl ...
- 数组类型与sizeof与指针的引用
以char类型为例: char a[100]; //a类型为char[100] &a类型为 char (*)[100] *a类型为char char *p = a; ...
- 挑战程序2.1.5 穷竭搜索>>宽度优先搜索
先对比一下DFS和BFS 深度优先搜索DFS 宽度优先搜索BFS 明显可以看出搜索顺序不同. DFS是搜索单条路径到 ...