POJ-1681

Painter‘s Problem

Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 4839   Accepted: 2350

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.

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 张嘉龄

/**
          题意:根据给出的图,问有多少种方法使得变为全‘y’
          做法:高斯消元 建一个n*n的矩阵
**/
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <algorithm>
#include <cmath>
#define maxn 250
using namespace std;
int mmap[maxn][maxn];
int x[maxn];
int equ,val;
char ch[20][20];
int free_x[maxn];
int gcd(int a,int b)
{
    if(b == 0) return a;
    return gcd(b,a%b);
}
int Lcm(int a,int b)
{
    return a/gcd(a,b)*b;
}
int Guess()
{
    int lcm;
    int ta;
    int tb;
    int max_r;
    int k;
    int col;
    col = 0;
    for(k = 0; k<equ&&col < val; k++,col++)
    {
        max_r = k;
        for(int i=k+1; i<equ; i++)
        {
            if(abs(mmap[i][col]) > abs(mmap[max_r][col]))
            {
                max_r = i;
            }
        }
        if(mmap[max_r][col] == 0)
        {
            k--;
            continue;
        }
        if(max_r != k)
        {
            for(int i=col; i<val+1; i++)
            {
                swap(mmap[max_r][i],mmap[k][i]);
            }
        }
        for(int i=k+1; i<equ; i++)
        {
            if(mmap[i][col] != 0)
            {
                for(int j=col; j<val+1; j++)
                {
                    mmap[i][j] ^= mmap[k][j];
                }
            }
        }
    }
    for(int i=k; i<equ; i++)
    {
        if(mmap[i][col] != 0) return -1;
    }
    for(int i=val-1; i>=0; i--)
    {
        x[i] = mmap[i][val];
        for(int j=i+1; j<val; j++)
        {
            x[i] ^= (mmap[i][j] & x[j]);
        }
    }
    return 0;
}
void init(int n)
{
    memset(x,0,sizeof(x));
    memset(mmap,0,sizeof(mmap));
    for(int i=0; i<n; i++)
    {
        for(int j=0; j<n; j++)
        {
            int tt = i * n +j;
            mmap[tt][tt] = 1;
            if(i > 0) mmap[(i-1)*n+j][tt] = 1;
            if(i < n-1) mmap[(i+1)*n+j][tt] = 1;
            if(j > 0) mmap[i*n + j - 1][tt] = 1;
            if(j < n-1) mmap[i*n + j + 1][tt] = 1;
        }
    }
}
void solve(int tt)
{
    int res = Guess();
    if(res == -1) printf("inf\n");
    else if(res == 0)
    {
        int ans = 0;
        for(int i=0; i<=tt; i++)
        {
            ans += x[i];
        }
        printf("%d\n",ans);
        return;
    }
    else
    {
        int ans = 0x3f3f3f3f;
        int tot = (1<<res);
        for(int i=0; i<tot; i++)
        {
            int cnt = 0;
            for(int j=0; j<res; j++)
            {
                if(i &(1<<j))
                {
                    x[free_x[j]] = 1;
                    cnt++;
                }
                else x[free_x[j]] = 0;
            }
            for(int j=val-tt-1; j>=0; j--)
            {
                                        int k;
                for( k=j; k<val; k++)
                    if(mmap[j][k]) break;
                x[k] = mmap[j][val];
                for(int l=k+1; l < val; l++)
                    if(mmap[j][l]) x[k] ^= x[l];
                cnt += x[k];

            }
            ans = min(ans,cnt);
        }
        printf("%d\n",ans);
    }
    return;
}
int main()
{
//#ifndef ONLINE_JUDGE
//    freopen("in.txt","r",stdin);
//#endif // ONLINE_JUDGE
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n;
        scanf("%d",&n);
        char c[28];
        init(n);
        int tt = n*n;
        equ = val = tt;
        for(int i=0; i<n; i++)
        {
            scanf("%s",c);
            for(int j=0; j<n; j++)
            {
                if(c[j] == ‘y‘) mmap[i*n+j][tt] = 0;
                else mmap[i*n+j][tt] = 1;

            }
        }
        solve(tt);
    }
    return 0;
}
时间: 2024-08-23 17:19:49

POJ-1681的相关文章

POJ 1681 Painter&#39;s Problem (高斯消元)

题目地址:POJ 1681 跟前两题几乎一模一样的...不多说了.高斯消元+自由元枚举. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #include <stdlib.h> #include <map> #include <set> #include &

POJ 1681 Painter&#39;s Problem (高斯消元)

题目链接 题意: 一个n*n 的木板 ,每个格子 都 可以 染成 白色和黄色,( 一旦我们对也个格子染色 ,他的上下左右 都将改变颜色): 给定一个初始状态 , 求将 所有的 格子 染成黄色 最少需要染几次?  若 不能 染成 输出 inf. 分析: 和1222差不多,唯一的区别是这个题还要求 最短的步数,其实只需要枚举一下最后的x[][]是否为1,即是否需要按下, 由于只有无解或者解唯一,因为按的顺序是没有影响的,所以只要是有解一定唯一,而且最短的情况是每个格子只按一次, 因为按两次以后就变为

poj 1681 Painter&amp;#39;s Problem(高斯消元)

http://poj.org/problem? id=1681 求最少经过的步数使得输入的矩阵全变为y. 思路:高斯消元求出自由变元.然后枚举自由变元,求出最优值. 注意依据自由变元求其它解及求最优值的方法. #include <stdio.h> #include <algorithm> #include <set> #include <map> #include <vector> #include <math.h> #include

POJ 1681 Painter&#39;s Problem 【高斯消元 二进制枚举】

任意门:http://poj.org/problem?id=1681 Painter's Problem Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 7667   Accepted: 3624 Description There is a square wall which is made of n*n small square bricks. Some bricks are white while some bric

POJ 1681 (开关问题+高斯消元法)

题目链接: http://poj.org/problem?id=1681 题目大意:一堆格子,或白或黄.每次可以把一个改变一个格子颜色,其上下左右四个格子颜色也改变.问最后使格子全部变黄,最少需要改变几个格子. 解题思路: 与POJ 1222类似. 一共只有15*15个格子,设初始解向量黄为0,白为1. 对于每个开关,设其改变状态为x5,上下左右四个开关改变状态分别为x1,x2,x3,x4, 那么有方程x1^x2^x3^x4^x5^初始状态=0. 这样就有15*15个方程.解这15*15个线性方

[ACM] POJ 2947 Widget Factory (高斯消元)

Widget Factory Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 4436   Accepted: 1502 Description The widget factory produces several different kinds of widgets. Each widget is carefully built by a skilled widgeteer. The time required to

poj 一类开关问题

这是一类开关问题,对于这类问题可以状态压缩枚举搞,也可以用高斯消元,当数据量比较大的时候高斯消元效率更高. poj 1222 状态压缩枚举第一行所有的翻转情况,从第二行开始依次递推即可. #include <iostream> #include <stdio.h> #include <string> #include <string.h> #include <algorithm> using namespace std; int dx[5]={0

高斯消元法(Gauss Elimination)【超详解&amp;模板】

高斯消元法,是线性代数中的一个算法,可用来求解线性方程组,并可以求出矩阵的秩,以及求出可逆方阵的逆矩阵.高斯消元法的原理是:若用初等行变换将增广矩阵 化为 ,则AX = B与CX = D是同解方程组. 所以我们可以用初等行变换把增广矩阵转换为行阶梯阵,然后回代求出方程的解. 1.线性方程组 1)构造增广矩阵,即系数矩阵A增加上常数向量b(A|b) 2)通过以交换行.某行乘以非负常数和两行相加这三种初等变化将原系统转化为更简单的三角形式(triangular form) 注:这里的初等变化可以通过

[Gauss]POJ1681 Painter&#39;s Problem

和POJ1222(http://www.cnblogs.com/Empress/p/4156234.html)完全相同 题意也类似, 可以涂自己以及上下左右五个位置的颜色 问几次能全部涂色 不能输出inf 1 #include <cstdio> 2 #include <cstdlib> 3 #include <cstring> 4 #include <climits> 5 #include <cctype> 6 #include <cmat

ACM第一阶段学习内容

一.知识目录 字符串处理 ................................................................. 3 1.KMP 算法 ............................................................ 3 2.扩展 KMP ............................................................ 6 3.Manacher 最长回文子串 .......