【2018寒假集训 Day1】【位运算】翻转游戏
2018-02-01 21:38
225 查看
翻转游戏(flip)
【问题描述】
翻转游戏是在一个 4 格×4 格的长方形上进行的,在长方形的 16 个格上每
个格子都放着一个双面的物件。每个物件的两个面,一面是白色,另一面是黑色,
每个物件要么白色朝上,要么黑色朝上,每一轮你只能翻 3 至 5 个物件,从而由
黑到白的改变这些物件上面的颜色,反之亦然。每一轮被选择翻转的物件遵循以
下规则:
1、从 16 个物件中任选一个。
2、翻转所选择的物件的同时,所有与它相邻的左方物件、右方物件、上方物件
和下方物件(如果有的话),都要跟着翻转。
以下为例:
bwbw
wwww
bbwb
bwwb
这里”b”表示该格子放的物件黑色面朝上、”w”表示该格子放的物件白色朝
上。如果我们选择翻转第三行的第一个物件(如图所示),那么格子状态将变为:
bwbw
bwww
wwwb
wwwb
游戏的目标是翻转到所有的物件白色朝上或黑色朝上。你的任务就是写一个
程序来求最少的翻转次数来实现这一目标。
【输入格式】flip.in
输入文件包含 4 行,每行 4 个字符,每个字符”w” 或 “b”表示游戏开始时格子
上物件的状态。
【输出格式】flip.out
输出文件仅一个整数,即从给定状态到实现这一任务的最少翻转次数。如果给定
的状态就已经实现了目标就输出 0,如果不可能实现目标就输出”Impossible”。
【输入样例】
bwwb
bbwb
bwwb
bwww
【输出样例】
4
【解题思路】
把黑白当作01,把图每一行相接形成一行,转换成01串后化成十进制。
用BFS对每一个点进行翻转,从一个图可以拓展出16种状态,接着继续拓展。
而对每一个点的翻转操作,可以利用位运算中的异或运算。
依照参考程序中的做法,对左上角的翻转操作就是异或19,对右下角的翻转操作就是异或51200。
计算方法就是把要翻转的位置当作是1,别的位置当作是0,按照开头的方法转化成01串后转化成10进制。
【参考程序】
【问题描述】
翻转游戏是在一个 4 格×4 格的长方形上进行的,在长方形的 16 个格上每
个格子都放着一个双面的物件。每个物件的两个面,一面是白色,另一面是黑色,
每个物件要么白色朝上,要么黑色朝上,每一轮你只能翻 3 至 5 个物件,从而由
黑到白的改变这些物件上面的颜色,反之亦然。每一轮被选择翻转的物件遵循以
下规则:
1、从 16 个物件中任选一个。
2、翻转所选择的物件的同时,所有与它相邻的左方物件、右方物件、上方物件
和下方物件(如果有的话),都要跟着翻转。
以下为例:
bwbw
wwww
bbwb
bwwb
这里”b”表示该格子放的物件黑色面朝上、”w”表示该格子放的物件白色朝
上。如果我们选择翻转第三行的第一个物件(如图所示),那么格子状态将变为:
bwbw
bwww
wwwb
wwwb
游戏的目标是翻转到所有的物件白色朝上或黑色朝上。你的任务就是写一个
程序来求最少的翻转次数来实现这一目标。
【输入格式】flip.in
输入文件包含 4 行,每行 4 个字符,每个字符”w” 或 “b”表示游戏开始时格子
上物件的状态。
【输出格式】flip.out
输出文件仅一个整数,即从给定状态到实现这一任务的最少翻转次数。如果给定
的状态就已经实现了目标就输出 0,如果不可能实现目标就输出”Impossible”。
【输入样例】
bwwb
bbwb
bwwb
bwww
【输出样例】
4
【解题思路】
把黑白当作01,把图每一行相接形成一行,转换成01串后化成十进制。
用BFS对每一个点进行翻转,从一个图可以拓展出16种状态,接着继续拓展。
而对每一个点的翻转操作,可以利用位运算中的异或运算。
依照参考程序中的做法,对左上角的翻转操作就是异或19,对右下角的翻转操作就是异或51200。
计算方法就是把要翻转的位置当作是1,别的位置当作是0,按照开头的方法转化成01串后转化成10进制。
【参考程序】
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int num; string st,sr; bool visit[65536]; struct data { int pic,step; }que[65536]; int trans(string st)//b当作是1,w当作是0,转换成十进制整数 { int ans=0,tmp=1; if (st[0]=='b') ans+=tmp; for (int i=1;i<=15;i++) { tmp=tmp<<1; if (st[i]=='b')ans+=tmp; } return ans; } const int table[16]={19,39,78,140,305,626,1252,2248,4880,10016,20032,35968,12544,29184,58368,51200};//打表 int bfs(int num) { if (num==0||num==65535) { cout<<0; return 0; } int head=0,tail=1; que[head].pic=num;que[head].step=0; visit[num]=true; while (head<tail) { for (int i=0;i<16;i++)//拓展 { que[tail].pic=que[head].pic^table[i];//翻转操作 if (!visit[que[tail].pic]) { que[tail].step=que[head].step+1; visit[que[tail].pic]=true; if (que[tail].pic==0||que[tail].pic==65535)//判断是否到达目标 { cout<<que[tail].step<<endl; return 0; } tail++; } } head++; } return -1; } int main() { freopen("flip.in","r",stdin); freopen("flip.out","w",stdout); cin>>st; cin>>sr;st=st+sr; cin>>sr;st=st+sr; cin>>sr;st=st+sr;//转化成一行 int num=trans(st); int ans=bfs(num); if (ans==-1) cout<<"Impossible"; return 0; }
相关文章推荐
- 【2018寒假集训 Day1】【位运算】桐桐的运输方案
- 2018寒假福州集训记Day1
- 【2018寒假集训Day 1】【位运算】生成字符串
- 2018寒假福州集训大总结
- 寒假▪福州集训 Day1
- 【2018寒假集训Day 7】【最短路径】三种算法的模板
- [置顶] 【集训Day3 单调队列】【2018寒假集训Day 5更新】最大子序列和
- 【2018寒假集训 Day2】【动态规划】回文字
- 【2018寒假集训Day 8】【最小生成树】Prim和Kruskal算法模板
- 【2018寒假集训 Day2】【动态规划】回文字
- 2018寒假DH省选集训模拟题1
- 【2018寒假集训 Day2】【动态规划】维修栅栏
- 2018福州集训DAY1
- 【2018寒假集训 Day2】【动态规划】垃圾陷阱(挖坑等填,未完成)
- 2018寒假集训总结第一节结构体
- 【2018寒假集训Day 8】【并查集】并查集模板
- 2018寒假福州集训记Day5
- 2014寒假ACM集训13级PK赛-翻转排序
- 2018寒假集训-紫皮书-全排列
- 【2018寒假集训 Day2】【动态规划】钱币兑换(exchange)(自己翻译的2333)