[Usaco2007 Open]Fliptile 翻格子游戏

Description

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”.

Input

* 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表示黑面向上.

Output

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

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

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

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.

solution

开始的时候打了dfs,看了题解之后立刻跪下.......

首先每个点只能翻1或0次,因为翻两次相当于翻过来又翻过去,与0次没有区别(类比异或)

有一个神奇但是不难看出(然而我没看出来)的性质:

当第一行每个点翻不翻确定时,整个矩阵就确定了

因为目标是全0.....

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cstring>
  4 #define mem(a,b) memset(a,b,sizeof(a))
  5 #define cop(a,b) memcpy(a,b,sizeof(a))
  6 using namespace std;
  7
  8 int n,m;
  9 int a[17][17],now[17][17];
 10 int b[17][17],ans[17][17];
 11 int maxp;
 12 int judge;
 13
 14 void bian(int x,int y)
 15 {
 16     b[x][y]^=1;
 17     if(x>1)b[x-1][y]^=1;
 18     if(x<n)b[x+1][y]^=1;
 19     if(y>1)b[x][y-1]^=1;
 20     if(y<m)b[x][y+1]^=1;
 21 }
 22
 23 int comp()
 24 {
 25     int numnow=0,numans=0;
 26     for(int i=1;i<=n;++i)
 27       for(int j=1;j<=m;++j)
 28       {
 29             numnow+=now[i][j];
 30             numans+=ans[i][j];
 31         }
 32     if(numnow!=numans)
 33       return numnow<numans;
 34     for(int i=1;i<=n;++i)
 35       for(int j=1;j<=n;++j)
 36         if(now[i][j]!=ans[i][j])
 37           return now[i][j]<ans[i][j];
 38 }
 39
 40 void jilu()
 41 {
 42     //printf("sdadsdsa\n");
 43     if(!judge)
 44     {
 45         judge=1;
 46         cop(ans,now);
 47         return ;
 48     }
 49     if(comp())
 50       cop(ans,now);
 51 }
 52
 53 int main(){
 54     //freopen("fliptile6.in","r",stdin);
 55     //freopen("fliptile.out","w",stdout);
 56     scanf("%d%d",&n,&m);
 57     maxp=(1<<m)-1;
 58     for(int i=1;i<=n;++i)
 59       for(int j=1;j<=m;++j)
 60         scanf("%d",&a[i][j]);
 61
 62     for(int k=0;k<=maxp;++k)
 63     {
 64         cop(b,a);
 65         for(int i=1;i<=m;++i)
 66         {
 67             if(k&(1<<(i-1)))
 68             {
 69               now[1][i]=1;
 70               bian(1,i);
 71             }
 72             else
 73               now[1][i]=0;
 74         }
 75         for(int i=2;i<=n;++i)
 76           for(int j=1;j<=m;++j)
 77           {
 78             if(b[i-1][j])
 79             {
 80                     now[i][j]=1;
 81                     bian(i,j);
 82                 }
 83                 else
 84                   now[i][j]=0;
 85             }
 86
 87         int flag=0;
 88         for(int i=1;i<=m;++i)
 89           if(b[n][i])
 90             flag=1;
 91         if(!flag)
 92           jilu();
 93     }
 94
 95     if(judge)
 96       for(int i=1;i<=n;++i)
 97       {
 98             for(int j=1;j<=m;++j)
 99               printf("%d ",ans[i][j]);
100             printf("\n");
101         }
102     else
103       printf("IMPOSSIBLE");
104     //while(1);
105     return 0;
106 }

code

时间: 2024-10-17 17:10:47

[Usaco2007 Open]Fliptile 翻格子游戏的相关文章

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

1647: [Usaco2007 Open]Fliptile 翻格子游戏 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 423  Solved: 173[Submit][Status][Discuss] Description Farmer John knows that an intellectually satisfied cow is a happy cow who will give more milk. He has arranged a

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

这个可以用异或高斯消元,但是我不会呀我用的暴搜 2的m次方枚举第一行的翻转情况,然后后面的就定了,因为对于一个j位置,如果i-1的j位置需要翻,那么一定要翻i的j,因为这是i-1的j最后翻的机会 按字典序搜索然后取次数min即可 #include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std;

[BZOJ 1647][USACO 2007 Open] Fliptile 翻格子游戏

1647: [Usaco2007 Open]Fliptile 翻格子游戏 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 702  Solved: 281[Submit][Status][Discuss] Description Farmer John knows that an intellectually satisfied cow is a happy cow who will give more milk. He has arranged a

Fliptile 翻格子游戏[Usaco2007 Open]

题目描述 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 i

赛码网算法: 格子游戏

格子游戏 题目描述 有n个格子,从左到右放成一排,编号为1-n.共有m次操作,有3种操作类型:1.修改一个格子的权值,2.求连续一段格子权值和,3.求连续一段格子的最大值.对于每个2.3操作输出你所求出的结果. 输入输入第一行两个整数,n表示格子个数,m表示操作次数,n和m中间用空格隔开:接下来输入n行,每行一个整数表示一个格子的权值接下来输入m行,每行有三个整数,中间用空格隔开:第一个是选择的操作类型1-3,第二和第三个整数是操作格子的编号.样例输入3 37892 1 33 1 32 1 2输

HDU 3537 Mock Turtles型翻硬币游戏

题目大意: 每次可以翻1个或者2个或者3个硬币,但要保证最右边的那个硬币是正面的,直到不能操作为输,这题目还有说因为主人公感情混乱可能描述不清会有重复的硬币说出,所以要去重 这是一个Mock Turtles型翻硬币游戏 下面是对这个类型游戏的讲解 约束条件6:每次可以翻动一个.二个或三个硬币.(Mock Turtles游戏) 初始编号从0开始. 当N==1时,硬币为:正,先手必胜,所以sg[0]=1. 当N==2时,硬币为:反正,先手必赢,先手操作后可能为:反反或正反,方案数为2,所以sg[1]

hdu2209翻纸牌游戏(bfs+状态压缩)

Problem Description 有一种纸牌游戏,很有意思,给你N张纸牌,一字排开,纸牌有正反两面,开始的纸牌可能是一种乱的状态(有些朝正,有些朝反),现在你需要整理这些纸牌.但是麻烦的是,每当你翻一张纸牌(由正翻到反,或者有反翻到正)时,他左右两张纸牌(最左边和最右边的纸牌,只会影响附近一张)也必须跟着翻动,现在给你一个乱的状态,问你能否把他们整理好,使得每张纸牌都正面朝上,如果可以,最少需要多少次操作. Input 有多个case,每个case输入一行01符号串(长度不超过20),1表

翻纸牌游戏(dfs回溯)

翻纸牌游戏 Time Limit : 9000/3000ms (Java/Other)   Memory Limit : 32768/32768K (Java/Other) Total Submission(s) : 2   Accepted Submission(s) : 2 Problem Description 有一种纸牌游戏,很有意思,给你N张纸牌,一字排开,纸牌有正反两面,开始的纸牌可能是一种乱的状态(有些朝正,有些朝反),现在你需要整理这些纸牌.但是麻烦的是,每当你翻一张纸牌(由正翻

HDU2209 ( 翻纸牌游戏 )

思路:枚举然后深搜,时间复杂度有点高. 代码: 1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 using namespace std; 6 int a[25]; 7 char c[25]; 8 int flag; 9 int len; 10 int judge() 11 { 12 int i,j; 13 int cnt=0; 14 for