问题 B: [Usaco2007 Open]Fliptile 翻格子游戏

时间限制: 5 Sec  内存限制: 128 MB

题目描述

Farmer John knows that an intellectually satisfied cow is a happy cow who will give more milk. He has arranged a brainy activity for cows in which they manipulate an M x N grid (1 <= M <= 15; 1 <= N <= 15) of square tiles, each of which is colored black on one side and white on the other side. As one would guess, when a single white tile is flipped, it changes to black; when a single black tile is flipped, it changes to white. The cows are rewarded when they flip the tiles so that each tile has the white side face up. However, the cows have rather large hooves and when they try to flip a certain tile, they also flip all the adjacent tiles (tiles that share a full edge with the flipped tile). Since the flips are tiring, the cows want to minimize the number of flips they have to make. Help the cows determine the minimum number of flips required, and the locations to flip to achieve that minimum. If there are multiple ways to achieve the task with the minimum amount of flips, return the one with the least lexicographical ordering in the output when considered as a string. If the task is impossible, print one line with the word "IMPOSSIBLE".

 约翰知道,那些高智力又快乐的奶牛产奶量特别高.所以他做了一个翻瓦片的益智游戏来娱乐奶牛.在一个M×N(1≤M,N≤15)的骨架上,每一个格子里都有一个可以翻转的瓦片.瓦片的一面是黑色的,而另一面是白色的.对一个瓦片进行翻转,可以使黑变白,也可以使白变黑.然而,奶牛们的蹄子是如此的巨大而且笨拙,所以她们翻转一个瓦片的时候,与之有公共边的相邻瓦片也都被翻转了.那么,这些奶牛们最少需要多少次翻转,使所有的瓦片都变成白面向上呢?如杲可以做到,输出字典序最小的结果(将结果当成字符串处理).如果不能做到,输出“IMPOSSIBLE”.

输入

* Line 1: Two space-separated integers: M and N

* Lines 2..M+1: Line i+1 describes the colors (left to right) of row i of the grid with N space-separated integers which are 1 for black and 0 for white

    第1行输入M和N,之后M行N列,输入游戏开始时的瓦片状态.0表示白面向上,1表示黑面向上.

输出

* Lines 1..M: Each line contains N space-separated integers, each specifying how many times to flip that particular location.

    输出M行,每行N个用空格隔开的整数,表示对应的格子进行了多少次翻转.

样例输入

4 4
1 0 0 1
0 1 1 0
0 1 1 0
1 0 0 1

样例输出

0 0 0 0
1 0 0 1
1 0 0 1
0 0 0 0 OUTPUT DETAILS: After flipping at row 2 column 1, the board will look like:
0 0 0 1
1 0 1 0
1 1 1 0
1 0 0 1 After flipping at row 2 column 4, the board will look like:
0 0 0 0
1 0 0 1
1 1 1 1
1 0 0 1 After flipping at row 3 column 1, the board will look like:
0 0 0 0
0 0 0 1
0 0 1 1
0 0 0 1 After flipping at row 3 column 4, the board will look like:
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0 Another solution might be:
0 1 1 0
0 0 0 0
0 0 0 0
0 1 1 0
but this solution is lexicographically higher than the solution above.

  考试第二题,由于有IMPOSSIBLE保底分,果断先做第三题,结果打完发现连IMPOSSIBLE都没时间打了,

/(ㄒoㄒ)/~~,借祥子的一句话,我招谁惹谁了!

  这道题先膜一下QTY_大佬,给我讲明白了,首先这道题一定是搜索,应该不用解释吧,那么这道题最棘手的是我把它翻过来它又会把相邻的几个翻过去,这就会是一个不断绕的过程了,莫名想到了网络流“王者之剑”,于是每个人都会有一个愿望,他如果每次只翻动一个格子就好了,于是乎我们可以注意到我每翻一个格子它的上下层只改变一个,那我们能否利用这个特性去搞他呢,答案是肯定的。

  由于是搜索题,我们不必去管每一次搜索是否一定对,而是去试暴力,那我们便可去枚举第一行我怎么翻,因为第一行翻法确定之后就可以采取近似贪心的策略,挨行去翻,只要上一行同一列的位置为1,我就翻它所对应的本行的位置知道最后一行,只要在最后加一个判断,去判断它最后一行是否都为0,是的话就是可行解,是的,可行解,因为题目要求字典序最小,这个我们待会再说,那我们怎么枚举第一行的翻法呢,感谢QTY_,状压就可以了,时间复杂度也是很好算的,状压是2^15,枚举就是枚举每个格子,最大才225,没毛病。

  那么我们再来解释下字典序这个烦人的东西,说实在的,题目给的字典序到底是怎么来的只能自己推,由样例和注释可知,即使1的个数一样也是有区别的,那么观察可发现样例输出的第一个1位置比注释中的解靠前,因此可以大胆的猜测可以以进制的思想去搞它。

  但这道题还没完,细心的人可能会发现本题中并未保证每个格子翻动次数只为1或0,也就是说每个格子在解中可能翻动了好几次,而按照上面的说法貌似只有0和1,是不是欺负数据水呢?当然不是假设有一种解为:

              0 1

              2 0

那么它完全等价为

              0 1

              0 0

以此类推,大于1只是可行解,不是最优解。

  

 #include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#include<cmath>
using namespace std;
int n,m,b[][];
int a[][],an[][];
int mn=0x7fffffff,mi,ans[][];
void dfs(int x){
memset(an,,sizeof(an));
memcpy(b,a,sizeof(a));
for(int i=;i<=n;i++)
{
if((<<(i-))&x)
{
an[][i]=;
b[][i]^=;
b[][i-]^=;
b[][i+]^=;
b[][i]^=;
}
}
for(int i=;i<=m;i++)
{
for(int j=;j<=n;j++)
{
if(b[i-][j])
{
an[i][j]=;
b[i-][j]^=;
b[i][j]^=;
b[i][j-]^=;
b[i][j+]^=;
b[i+][j]^=;
}
}
}
bool yx=;
for(int i=;i<=n;i++)
{
if(b[m][i])
{
yx=;
break;
}
} if(yx)
{ int js=,be=;
for(int i=;i<=m;i++)
{
for(int j=;j<=n;j++)
{
if(an[i][j])
{
js++;
if(!be)
be=(i-)*+j;
}
}
}
if(js<mn)
{
mn=js;
mi=be;
memcpy(ans,an,sizeof(an));
}
else if(js==mn&&be<mi)
{
mi=be;
memcpy(ans,an,sizeof(an));
}
}
}
int main(){
scanf("%d%d",&m,&n);
for(int i=;i<=m;i++)
{
for(int j=;j<=n;j++)
{
scanf("%d",&a[i][j]);
}
}
for(int i=;i<(<<n);i++)
{
dfs(i);
}
if(mn==0x7fffffff)
{
printf("IMPOSSIBLE\n");
}
else
{
for(int i=;i<=m;i++)
{
for(int j=;j<=n;j++)
printf("%d ",ans[i][j]);
printf("\n");
}
}
return ;
}

[Usaco2007 Open]Fliptile 翻格子游戏题解的更多相关文章

  1. 1647: [Usaco2007 Open]Fliptile 翻格子游戏

    1647: [Usaco2007 Open]Fliptile 翻格子游戏 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 423  Solved: 173[ ...

  2. [Usaco2007 Open]Fliptile 翻格子游戏

    [Usaco2007 Open]Fliptile 翻格子游戏 题目 Farmer John knows that an intellectually satisfied cow is a happy ...

  3. 【BZOJ】1647: [Usaco2007 Open]Fliptile 翻格子游戏(暴力)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1647 自己太弱...看题解.. 竟然是枚举第一行的放法,,,因为一定要全部变0,所以将前一行1的在这 ...

  4. [Usaco2007 Open]Fliptile 翻格子游戏 状态压缩

    考试想到了状压,苦于T1废掉太长时间,于是默默输出impossible.. 我们知道,一个格子的翻转受其翻转次数和它相邻翻转次数的影响. 由每一个位置操作两次相当于把它翻过来又翻回去,所以答案中每一个 ...

  5. 【BZOJ 1647】[Usaco2007 Open]Fliptile 翻格子游戏 模拟、搜索

    第一步我们发现对于每一个格子,我们只有翻和不翻两种状态,我们发现一旦确定了第一行操作,那么第二行的操作也就随之确定了,因为第一行操作之后我们要想得到答案就得把第一行全部为0,那么第二行的每一个格子的操 ...

  6. BZOJ 1647 [Usaco2007 Open]Fliptile 翻格子游戏:部分枚举 位运算

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1647 题意: 在一个n*m(1 <= n,m <= 15)的棋盘上,每一个格子 ...

  7. bzoj 1647: [Usaco2007 Open]Fliptile 翻格子游戏【dfs】

    这个可以用异或高斯消元,但是我不会呀我用的暴搜 2的m次方枚举第一行的翻转情况,然后后面的就定了,因为对于一个j位置,如果i-1的j位置需要翻,那么一定要翻i的j,因为这是i-1的j最后翻的机会 按字 ...

  8. [Usaco2007 Open]Fliptile 翻格子游戏 状压dp

    n,m<=15,直接搞肯定不行,考虑一行一行来, 每一行的状态只与三行有关,所以从第一行开始枚举,每一次让下面一行填上他上面那行的坑 最后一行必须要同时满足他自己和他上面那行,否则舍去 #inc ...

  9. Fliptile 翻格子游戏

    问题 B: [Usaco2007 Open]Fliptile 翻格子游戏 时间限制: 5 Sec  内存限制: 128 MB 题目描述 Farmer John knows that an intell ...

随机推荐

  1. 自定义View实现图片热区效果

    我司主要从事工业物联网领域软件的开发,现有个需求,在外废品处理时需要对产品的不良位置进行标记,点选图片实现图片网格的着色功能. 需求是通过自定义view来实现,实现思路如下: 首先将点击的小方格对象实 ...

  2. SQL Server 限制IP登陆(登陆触发器运用)

    原文:SQL Server 限制IP登陆(登陆触发器运用) 一.本文所涉及的内容(Contents) 本文所涉及的内容(Contents) 背景(Contexts) 实现代码(SQL Codes) 补 ...

  3. C语言实现的CRC16/CCITT-FALSE校验码函数

    要求:输入字符串“00 AA FF CC AA 01 00” 得到校验码“79B1” 方法1: // ConsoleApplication1.cpp: 定义控制台应用程序的入口点. // #inclu ...

  4. Android零基础入门第57节:日期选择器DatePicker和时间选择器TimePicker

    原文:Android零基础入门第57节:日期选择器DatePicker和时间选择器TimePicker 在实际开发中,经常会遇见一些时间选择器.日期选择器.数字选择器等需求,那么从本期开始来学习And ...

  5. DataTable,DataView 排序和使用

    我们都知道在Sql Server可以用order by来排序,所以很多朋友在DataTable中排序也想到了用order by关键字.但这样实现是比较困难的,下面,我们讲解一种比较简单的方法: 控制台 ...

  6. linux输出信息调试信息重定向

    最近在做一个android系统移植的项目,所使用的开发板com1是调试串口,就是说会有uboot和kernel的调试信息打印在com1上(ttySAC0).因为后期要使用ttySAC0作为上层应用通信 ...

  7. Qt编程规范

    一.概述 良好的编程规范可以大幅提高一个程序的可读性.可理解性和可维护性. 本规范参考Effective C++中文版.Google C++编码规范及Qt编码风格. 二.头文件 1)      #de ...

  8. 注册表Demo

    一.获取安装程序信息 #include <windows.h> #include <iostream> #include <string> #include < ...

  9. ab fails to connect to localhost

    The following command fails: $ ab -n 1 localhost:8000/ ... Benchmarking localhost (be patient)...apr ...

  10. What?Tomcat-竟然也算中间件?

    关于 MyCat 的铺垫文章已经写了两篇了: MySQL 只能做小项目?松哥要说几句公道话! 北冥有 Data,其名为鲲,鲲之大,一个 MySQL 放不下! 今天是最后一次铺垫,后面就可以迎接大 Bo ...