标签:
Description
Consider the following position as an example: Input
Output
Sample Input
bwwb bbwb bwwb bwww
Sample Output
4
黑白棋翻转问题,搜索,枚举都可以做,这次用它来练习高斯消元做法
每个有关系的系数为1,每个棋子是否翻转确定了结果是0还是1,得到了异或方程组,使用高斯消元,找出自由元,然后转化为二进制后,枚举自由元,找出最优解。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;
#define INF 0x3f3f3f3f
int Map[20][20] , a[20] , min1 , x[20] , freex[20] ;
char str[5][5] ;
void getMap(int k)
{
int i , j ;
memset(Map,0,sizeof(Map)) ;
for(i = 0 ; i < 4 ; i++)
{
for(j = 0 ; j < 4 ; j++)
{
a[i*4+j] = (str[i][j] - '0') ^ k ;
Map[i*4+j][i*4+j] = 1 ;
if( i > 0 )
Map[i*4+j][i*4+j-4] = 1 ;
if( i < 3 )
Map[i*4+j][i*4+j+4] = 1 ;
if( j > 0 )
Map[i*4+j][i*4+j-1] = 1 ;
if( j < 3 )
Map[i*4+j][i*4+j+1] = 1 ;
}
}
return ;
}
void swap1(int p,int q)
{
int j , temp ;
temp = a[p] ;
a[p] = a[q] ;
a[q] = temp ;
for(j = 0 ; j < 16 ; j++)
{
temp = Map[p][j] ;
Map[p][j] = Map[q][j] ;
Map[q][j] = temp ;
}
return ;
}
int solve()
{
int i , j , k , t = 0 , num1 = 0 ;
for(i = 0 ; i < 16 && t < 16 ; t++ , i++)
{
for(j = i ; j < 16 ; j++)
if( Map[j][t] )
break ;
if( j == 16 )
{
freex[num1++] = t ;
i-- ;
continue ;
}
if( i != j )
swap1(i,j) ;
for(j = i+1 ; j < 16 ; j++)
{
if( Map[j][t] )
{
a[j] = a[j]^a[i] ;
for(k = t ; k < 16 ; k++)
Map[j][k] = Map[j][k] ^ Map[i][k] ;
}
}
}
for( ; i < 16 ; i++)
if( a[i] )
return -1 ;
if( num1 ) return num1 ;
for(i = 15 ; i >= 0 ; i--)
{
x[i] = a[i] ;
for(j = i+1 ; j < 16 ; j++)
x[i] = x[i]^(Map[i][j]*x[j]) ;
}
return num1 ;
}
int f(int s)
{
int i , j , k , key , ans , min1 = INF ;
getMap(s) ;
key = solve() ;
ans = 0 ;
if( key == 0 )
{
ans = 0 ;
for(i = 0 ; i < 16 ; i++)
ans += x[i] ;
min1 = min(min1,ans) ;
}
else if( key > 0 )
{
int temp = 1<<key ;
for(int t = 0 ; t < temp ; t++)
{
memset(x,0,sizeof(x)) ;
ans = 0 ;
for(j = 0 ; j < key ; j++)
if( t & (1<<j) )
{
x[ freex[j] ] = 1 ;
ans++ ;
}
for(i = 15 ; i >= 0 ; i--)
{
for(k = 0 ; k < 16 ; k++)
if( Map[i][k] )
break ;
x[k] = a[i] ;
for(j = k+1 ; j < 16 ; j++)
x[k] ^= (Map[i][j]*x[j]) ;
ans += x[k] ;
}
min1 = min(min1,ans) ;
}
}
return min1 ;
}
int main()
{
int i , j , min1 = INF , k , ans , temp ;
for(i = 0 ; i < 4 ; i++)
{
scanf("%s", str[i]) ;
for(j = 0 ; j < 4 ; j++)
{
if( str[i][j] == 'b' )
str[i][j] = '0' ;
else
str[i][j] = '1' ;
}
}
ans = f(0) ;
min1 = min(min1,ans) ;
ans = f(1) ;
min1 = min(min1,ans) ;
if( min1 == INF )
printf("Impossible\n") ;
else
printf("%d\n", min1) ;
return 0;
}
poj1753--Flip Game(高斯消元问题2,枚举自由元的首杀)
标签:
原文地址:http://blog.csdn.net/winddreams/article/details/43152305