Flip Game
Time Limit: 3000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others)
Flip game is played on a rectangular 4×44×4 field with two-sided pieces placed on each of its 1616 squares. One side of each piece is white and the other one is black and each piece is lying either it's black or white side up. Each round you flip 33 to 55 pieces, thus changing the color of their upper side from black to white and vice versa. The pieces to be flipped are chosen every round according to the following rules:
Choose any one of the 1616 pieces. Flip the chosen piece and also all adjacent pieces to the left, to the right, to the top, and to the bottom of the chosen piece (if there are any).
Consider the following position as an example:
bwbw
wwww
bbwb
bwwb
Here b
denotes pieces lying their black side up and w
denotes pieces lying their white side up. If we choose to flip the 1st1st piece from the 3rd3rd row (this choice is shown at the picture), then the field will become:
bwbw
bwww
wwwb
wwwb
The goal of the game is to flip either all pieces white side up or all pieces black side up. You are to write a program that will search for the minimum number of rounds needed to achieve this goal.
Input
There are only one test case in the input file.
The input consists of 44 lines with 44 characters w
or b
each that denote game field position.
Output
Write to the output file a single integer number - the minimum number of rounds needed to achieve the goal of the game from the given position. If the goal is initially achieved, then write 0. If it's impossible to achieve the goal, then write the word Impossible
(without quotes).
Sample input and output
Sample Input | Sample Output |
---|---|
bwwb bbwb bwwb bwww |
4 |
Source
|
按第1个格 |
按第2个格 |
按第3个格 |
按第4个格 |
|
第1个格 |
1 |
1 |
0 |
0 |
|
第2个格 |
1 |
1 |
1 |
0 |
|
第3个格 |
0 |
1 |
1 |
1 |
|
第4个格 |
0 |
0 |
1 |
1 |
|
第5个格 |
1 |
0 |
0 |
0 |
|
第6个格 |
0 |
1 |
0 |
0 |
|
第7个格 |
0 |
0 |
1 |
0 |
|
第8个格 |
0 |
0 |
0 |
1 |
|
/**
2016 - 09 - 05 下午
Author: ITAK
Motto:
今日的我要超越昨日的我,明日的我要胜过今日的我,
以创作出更好的代码为目标,不断地超越自己。
**/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <queue>
#include <algorithm>
#include <set>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const int INF = 1e9+5;
const int MAXN = 20;
const int MOD = 1e9+7;
const double eps = 1e-7;
const double PI = acos(-1);
using namespace std;
LL Scan_LL()///输入外挂
{
LL res=0,ch,flag=0;
if((ch=getchar())=='-')
flag=1;
else if(ch>='0'&&ch<='9')
res=ch-'0';
while((ch=getchar())>='0'&&ch<='9')
res=res*10+ch-'0';
return flag?-res:res;
}
int Scan_Int()///输入外挂
{
int res=0,ch,flag=0;
if((ch=getchar())=='-')
flag=1;
else if(ch>='0'&&ch<='9')
res=ch-'0';
while((ch=getchar())>='0'&&ch<='9')
res=res*10+ch-'0';
return flag?-res:res;
}
void Out(LL a)///输出外挂
{
if(a>9)
Out(a/10);
putchar(a%10+'0');
}
int equ, var;///equ个方程 var个变量
int a[MAXN][MAXN];///增广矩阵
int x[MAXN];///解集
int x_i[MAXN];
bool free_x[MAXN];///判断是不是自由变元
int free_num;///自由变元的个数
inline int GCD(int m, int n)
{
if(n == 0)
return m;
return GCD(n, m%n);
}
inline int LCM(int a, int b)
{
return a/GCD(a,b)*b;
}
int Gauss()
{
int Max_r;///当前列绝对值最大的存在的行
///col:处理当前的列
int row,col = 0;
int free_x_num;
int free_index;
free_num = 0;
for(int i=0; i<=var; i++)
{
x[i] = 0;
free_x[i] = 1;
}
for(row=0; row<equ&&col<var; row++,col++)
{
Max_r = row;
for(int i=row+1; i<equ; i++)
if(abs(a[i][col]) > abs(a[Max_r][col]))
Max_r = i;
if(a[Max_r][col] == 0)
{
free_x[col] = 1;
x_i[free_num++] = col;
}
if(Max_r != row)
for(int i=0; i<var+1; i++)
swap(a[row][i], a[Max_r][i]);
if(a[row][col] == 0)
{
row--;
continue;
}
for(int i=row+1; i<equ; i++)
{
if(a[i][col])
{
int lcm = LCM(abs(a[i][col]), abs(a[row][col]));
int tp1=lcm/abs(a[i][col]), tp2=lcm/abs(a[row][col]);
if(a[row][col]*a[i][col] < 0)
tp2 = -tp2;
for(int j=col; j<var+1; j++)
a[i][j] = ( (tp1*a[i][j]-tp2*a[row][j]) % 2 + 2 ) % 2;
}
}
}
for(int i=row; i<equ; i++)
if(a[i][col])
return -1;///无解
///保证对角线主元非 0
for(int i=0; i<equ; i++)
{
if(!a[i][i])
{
int j;
for(j=i+1; j<var; j++)
if(a[i][j])
break;
if(j == var)
break;
for(int k=0; k<equ; k++)
swap(a[k][i], a[k][j]);
}
}
if(row < var)
{
for(int i=row-1; i>=0; i--)
{
free_x_num = 0;
for(int j=0; j<var; j++)
if(a[i][j] && free_x[j])
{
free_x_num++;
free_index = j;
}
if(free_x_num > 1)
continue;
int tmp = a[i][var];
for(int j=0; j<var; j++)
if(a[i][j] && j!=free_index)
tmp = ((tmp - a[i][j]*x[j]) % 2 + 2) % 2;
x[free_index] = (tmp/a[i][i])%2;/// 求出该变元.
free_x[free_index] = 0; /// 该变元是确定的.
}
return var - row;///自由变元的个数
}
///回代
for(int i=var-1; i>=0; i--)
{
int tmp = a[i][var] % 2;
for(int j=i+1; j<var; j++)
if (a[i][j])
tmp = ((tmp - a[i][j]*x[j]) % 2 + 2) % 2;
if (tmp%a[i][i])
return -2; /// 说明有浮点数解,但无整数解.
x[i] = (tmp/a[i][i])%2;
}
return 0;///唯一解
}
void Init()
{
memset(a, 0, sizeof(a));
memset(x, 0, sizeof(x));
for(int i=0; i<var; i++)
{
int ta = i % 4, tb = i / 4;
a[i][i] = 1;
if(ta > 0)
a[i-1][i] = 1;
if(tb > 0)
a[i][i-4] = 1;
if(ta < 3)
a[i+1][i] = 1;
if(tb < 3)
a[i][i+4] = 1;
}
}
void Debug()
{
puts("");
cout<<"+++++++++++++++++++++++++++分界线++++++++++++++++++++++++++++++"<<endl;
for(int i=0; i<equ; i++)
{
for(int j=0; j<var+1; j++)
{
cout<<a[i][j]<<" ";
}
cout<<endl;
}
cout<<"+++++++++++++++++++++++++++分界线++++++++++++++++++++++++++++++"<<endl;
puts("");
}
int Solve()
{
int ans = 0;
for(int i=0; i<var; i++)
ans += x[i];
///cout<<ans<<endl;
return ans;
}
char str[10][10];
int b[MAXN][MAXN];
int main()
{
equ = var = 16;
/**Init();
Gauss();
Debug();*/
while(~scanf("%s",str[0]))
{
for(int i=1; i<4; i++)
scanf("%s",str[i]);
Init();
for(int i=0; i<4; i++)
for(int j=0; j<4; j++)
if(str[i][j] == 'w')
a[i*4+j][var] = 1;
int cnt = Gauss(), ans = INF;
if(cnt == -1)
{
puts("Impossible");
continue;
}
///Debug();
for(int i=0; i<(1<<cnt); i++)
{
for(int j=0; j<cnt; j++)
if(i & (1<<j))
x[x_i[j]] = 1;
else
x[x_i[j]] = 0;
for(int ii=var-cnt-1; ii>=0; ii--)
{
int tmp = a[ii][var] % 2;
for(int j=ii+1; j<var; j++)
if(a[ii][j])
tmp = ((tmp - a[ii][j]*x[j]) % 2 + 2) % 2;
x[ii] = (tmp/a[ii][ii])%2;
}
ans = min(ans, Solve());
}
Init();
for(int i=0; i<4; i++)
for(int j=0; j<4; j++)
if(str[i][j] == 'b')
a[i*4+j][var] = 1;
cnt = Gauss();
for(int i=0; i<(1<<cnt); i++)
{
for(int j=0; j<cnt; j++)
if(i & (1<<j))
x[x_i[j]] = 1;
else
x[x_i[j]] = 0;
for(int ii=var-cnt-1; ii>=0; ii--)
{
int tmp = a[ii][var] % 2;
for(int j=ii+1; j<var; j++)
if(a[ii][j])
tmp = ((tmp - a[ii][j]*x[j]) % 2 + 2) % 2;
x[ii] = (tmp/a[ii][ii])%2;
}
ans = min(ans, Solve());
}
cout<<ans<<endl;
}
return 0;
}