现在的位置: 首页 > 综合 > 正文

POJ1681——Painter\’s Problem

2019年02月15日 ⁄ 综合 ⁄ 共 2787字 ⁄ 字号 评论关闭

Description

There is a
square wall which is made of n*n small square bricks. Some bricks are
white while some bricks are yellow. Bob is a painter and he wants to
paint all the bricks yellow. But there is something wrong with Bob's
brush. Once he uses this brush to paint brick (i, j), the bricks at (i,
j), (i-1, j), (i+1, j), (i, j-1) and (i, j+1) all change their color.
Your task is to find the minimum number of bricks Bob should paint in
order to make all the bricks yellow.

POJ1681——Painters Problem - Alex - Alex

Input

The
first line contains a single integer t (1 <= t <= 20) that
indicates the number of test cases. Then follow the t cases. Each test
case begins with a line contains an integer n (1 <= n <= 15),
representing the size of wall. The next n lines represent the original
wall. Each line contains n characters. The j-th character of the i-th
line figures out the color of brick at position (i, j). We use a 'w' to
express a white brick while a 'y' to express a yellow brick.

Output

For
each case, output a line contains the minimum number of bricks Bob
should paint. If Bob can't paint all the bricks yellow, print 'inf'.

Sample Input

2
3
yyy
yyy
yyy
5
wwwww
wwwww
wwwww
wwwww
wwwww

Sample Output

0
15

Source

POJ Monthly--2004.06.27 张嘉龄

高斯消元法解异或方程组.

得到的每个方程类似与mat[0][0]*x[0] ^ mat[0][1]^X[1] ^ .....^mat[0][var-1]*x[var-1]  = b[0]
我们把矩阵的第i行上和第i个开关有关系的那些系数赋值为1,其他的为0,在最后一列放置那个开关的初态和末态的改变,得到增广矩阵,高消之后枚举自由变量找到最少操作数即可。

//高斯消元法解异或方程组,poj1681

#include<stdio.h>
#include<math.h>
#include<string.h>
#include<iostream>
#include<algorithm>

using namespace std;

const int maxn=300;
int x[maxn];//存最后的解
int mat[maxn][maxn];
int free_x[maxn];//存自由变元

int Gauss(int equ,int var)
{
int i,j,k;
int free_index,free_num;
int max_r,col,num;
col=0;
num=0;
for(k=0;k<equ && col<var;k++,col++)
{
max_r=k;//找到col列上绝对值最大的那行(k行的下面那些行)
for(i=k+1;i<equ;i++)
{
if(abs(mat[i][col]) > abs(mat[max_r][col]))
max_r=i;
}
if(max_r!=k)//找到后和第k行交换
{
for(j=k;j<var+1;j++)
swap(mat[k][j],mat[max_r][j]);
}
if(!mat[k][col])
{
k--;
//free_x[num++]=col;//如果第k行第col这个数为0,也就是系数为0,那他就是个自由变量
continue;
}
for(i=k+1;i<equ;i++)
{
if(mat[i][col])
{
for(j=col;j<var+1;j++)
mat[i][j]^=mat[k][j];//异或以后消去k+1行到最后一行的第col列的系数,形成上三角矩阵
}
}
}
for(i=k;i<equ;i++)
if(mat[i][col])
return -1;//无解
//接下来得枚举自由变元
int all=1<<(var-k);//var-k个自由变元,那么有2的指数次个状态
int t=0;
int res=0x3f3f3f3f;
for(j=k-1;j>=0;j--)
{
int temp=mat[j][var];
for(int l=j+1;l<var;l++)
temp^=mat[j][l]*x[l];
x[j]=temp;
if(x[j])
t++;
}
for(i=0;i<all;i++)
{
int cnt=t;
int index=i;
for(j=0;j<var-k;j++)
{
//x[free_x[j]]=(index&1);
if(index&1)//如果是1,则要反转,也就是要操作一次
cnt++;
index>>=1;
}
//同时还要判断确定的变量
if(cnt < res)
res = cnt;
}
return res;
}

char str[30];

int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
memset(mat,0,sizeof(mat));
memset(x,0,sizeof(mat));
memset(free_x,1,sizeof(free_x));
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
{
int t=i*n+j;
mat[t][t]=1;
if(i>0)
mat[(i-1)*n+j][t]=1;
if(i<n-1)
mat[(i+1)*n+j][t]=1;
if(j>0)
mat[i*n+j-1][t]=1;
if(j<n-1)
mat[i*n+j+1][t]=1;
}
for(int i=0;i<n;i++)
{
scanf("%s",str);
for(int j=0;j<n;j++)
{
if(str[j]=='y')
mat[i*n+j][n*n]=0;
else
mat[i*n+j][n*n]=1;
}
}
int res=Gauss(n*n,n*n);
if(res<0)
printf("inf\n");
else
printf("%d\n",res);
}
return 0;
}

抱歉!评论已关闭.