POJ 3279 Fliptile(反转)
2015-08-30 08:41
477 查看
Description
一个m*n的格子,每个格子可以反转正反面,一面黑一面白,农夫约翰的牛现在玩游戏,把所有格子都反转成白色,因牛蹄很大,每次反转一个格子会让其上下左右相邻接的格子也反转。现在给定格子颜色,求最少操作次数完成该游戏,如果不能完成则输出IMPOSSIBLE
Input
第一行两个整数m和n表示格子的行列数,之后一个m*n矩阵表示格子颜色,0表示白色,1表示黑色
Output
如能完成游戏则输出最少步数,如果不能则输出IMPOSSIBLE
Sample Input
4 4
1 0 0 1
0 1 1 0
0 1 1 0
1 0 0 1
Sample Output
0 0 0 0
1 0 0 1
1 0 0 1
0 0 0 0
Solution
因为最后格子状态只能为全黑或全白,以将格子变成全黑为例,首先枚举第一行的反转情况,然后一行行向下递推,后面格子的反转必须使得前一行格子变成黑色,这样一来当将第四行反转完后前三行都为黑色,这时只需判断第四行是否全黑即可,对于每次满足条件的枚举枚举更新最小反转次数
Code
一个m*n的格子,每个格子可以反转正反面,一面黑一面白,农夫约翰的牛现在玩游戏,把所有格子都反转成白色,因牛蹄很大,每次反转一个格子会让其上下左右相邻接的格子也反转。现在给定格子颜色,求最少操作次数完成该游戏,如果不能完成则输出IMPOSSIBLE
Input
第一行两个整数m和n表示格子的行列数,之后一个m*n矩阵表示格子颜色,0表示白色,1表示黑色
Output
如能完成游戏则输出最少步数,如果不能则输出IMPOSSIBLE
Sample Input
4 4
1 0 0 1
0 1 1 0
0 1 1 0
1 0 0 1
Sample Output
0 0 0 0
1 0 0 1
1 0 0 1
0 0 0 0
Solution
因为最后格子状态只能为全黑或全白,以将格子变成全黑为例,首先枚举第一行的反转情况,然后一行行向下递推,后面格子的反转必须使得前一行格子变成黑色,这样一来当将第四行反转完后前三行都为黑色,这时只需判断第四行是否全黑即可,对于每次满足条件的枚举枚举更新最小反转次数
Code
#include<cstdio> #include<cstring> #include<iostream> #include<queue> using namespace std; #define maxn 16 const int dx[5]={-1,0,0,0,1};//邻接格子坐标 const int dy[5]={0,-1,0,1,0}; int m,n; int map[maxn][maxn];//格子初始状态 int ans[maxn][maxn];//保存最优解 int temp[maxn][maxn];//保存中间结果 int get(int x,int y)//查询(x,y)的颜色 { int c=map[x][y]; for(int i=0;i<5;i++) { int xx=x+dx[i],yy=y+dy[i]; if(xx>=0&&xx<m&&yy>=0&&yy<n) c+=temp[xx][yy]; } return c%2; } int solve()//求出第一行确定情况下的最少操作次数,不存在返回-1 { for(int i=1;i<m;i++) for(int j=0;j<n;j++) if(get(i-1,j)!=0)//(i-1,j)是黑色,则必须反转此格子 temp[i][j]=1; for(int j=0;j<n;j++)//判断最后一行是否为全白 if(get(m-1,j)!=0)//无解 return -1; int res=0; for(int i=0;i<m;i++)//统计反转次数 for(int j=0;j<n;j++) res+=temp[i][j]; return res; } int main() { scanf("%d%d",&m,&n); for(int i=0;i<m;i++) for(int j=0;j<n;j++) scanf("%d",&map[i][j]); int res=-1; for(int i=0;i<1<<n;i++)//按照字典序尝试第一行所有可能性 { memset(temp,0,sizeof(temp));//初始化 for(int j=0;j<n;j++) temp[0][n-1-j]=i>>j&1; int num=solve(); if(num>=0&&(res<0||res>num)) { res=num;//更新最少操作次数 memcpy(ans,temp,sizeof(temp));//复制最优解 } } if(res<0)//无解 printf("IMPOSSIBLE\n"); else for(int i=0;i<m;i++) for(int j=0;j<n;j++) printf("%d%c",ans[i][j],j==n-1?'\n':' '); return 0; }
相关文章推荐
- CodeForces 574C - Bear and Poker
- POJ 3264 Balanced Lineup(ST)
- 在MyEclipse中建立Maven项目
- 微软宣布:Win10小型更新日志详情只提供给企业版用户
- Win10 Build 10532语言包官方下载地址汇总
- Vugen 和controller 中的run-time setting有什么不同?--性能测试学习总结9
- POJ 3183 Stump Removal(水~)
- POJ 3176 Cow Bowling(dp)
- CodeForces 574A - Bear and Elections
- 《HTTP权威指南》学习笔记(五)
- POJ 3158 Kickdown(水~)
- POJ 3117 World Cup(水~)
- POJ 3100 && HDU 2740 Root of the Problem(水~)
- POJ 3096 && HDU 2736 Surprising Strings(水~)
- 类加载和对象的初始化过程
- 《HTTP权威指南》学习笔记(四)
- codecombat之Sarven沙漠13-24关及森林45/46关代码分享
- POJ 3094 && HDU 2734 Quicksum(水~)
- POJ 3087 Shuffle'm Up(简单模拟)
- hdu5422 Rikka with Graph(图论简单规律题)