POJ 1681 Painter'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 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 张嘉龄

题意概括:

一个二维矩阵, 输入每个格子的初始颜色,可以进行的操作是 粉刷一个格子则相邻的上下左右四个各自颜色都会取反(只有两种颜色);

问最后把全部各自涂成黄色的最小操作数;

解题思路:

根据题意,每个各自都是一个变元,根据各自之间的相邻关系构造增广矩阵;

高斯消元求出自由元个数 sum;

二进制枚举方案,找出最小的操作数;

AC code:

  1 #include <cstdio>
  2 #include <iostream>
  3 #include <algorithm>
  4 #include <cstring>
  5 #define INF 0x3f3f3f3f
  6 #define LL long long
  7 using namespace std;
  8 const int MAXN = 300;
  9
 10 int equ, var;
 11 int a[MAXN][MAXN];
 12 char str[MAXN][MAXN];
 13 int x[MAXN];
 14 int free_x[MAXN];
 15 int free_num;
 16 int N;
 17
 18 int Gauss()
 19 {
 20     int maxRow, col, k;
 21     free_num = 0;
 22     for(k = 0, col = 0; k < equ && col < var; k++, col++){
 23         maxRow = k;
 24         for(int i = k+1; i <equ; i++){
 25             if(abs(a[i][col]) > abs(a[maxRow][col]))
 26                 maxRow = i;
 27         }
 28         if(a[maxRow][col] == 0){                //最大的都为0说明该列下面全是 0
 29             k--;
 30             free_x[free_num++] = col;           //说明col是自由元
 31             continue;
 32         }
 33         if(maxRow != k){                        //交换行
 34             for(int j = col; j < var+1; j++)
 35                 swap(a[k][j], a[maxRow][j]);
 36         }
 37         for(int i = k+1; i < equ; i++){             //消元
 38             if(a[i][col] != 0){
 39                 for(int j = col; j < var+1; j++){
 40                     a[i][j] ^= a[k][j];
 41                 }
 42             }
 43         }
 44     }
 45     for(int i = k; i< equ; i++){
 46         if(a[i][col] != 0) return -1;   //无解
 47     }
 48     if(k < var) return var-k;           //返回自由元个数
 49
 50     for(int i = var-1; i >= 0; i--){    //唯一解,回代
 51         x[i] = a[i][var];
 52         for(int j = i+1; j < var; j++){
 53             x[i] ^= (a[i][j] && x[j]);
 54         }
 55     }
 56     return 0;
 57 }
 58
 59 void init()
 60 {
 61     memset(a, 0, sizeof(a));
 62     memset(x, 0, sizeof(x));
 63     equ = N*N;
 64     var = N*N;
 65     for(int i = 0; i < N; i++){                 //构造增广矩阵
 66         for(int j = -0; j < N; j++){
 67             int t = i*N+j;
 68             a[t][t] = 1;
 69             if(i > 0) a[(i-1)*N+j][t] = 1;
 70             if(i < N-1) a[(i+1)*N+j][t] = 1;
 71             if(j > 0) a[i*N+j-1][t] = 1;
 72             if(j < N-1) a[i*N+j+1][t] = 1;
 73         }
 74     }
 75 }
 76
 77 void solve()
 78 {
 79     int t = Gauss();
 80     if(t == -1){            //无解
 81         printf("inf\n");
 82         return;
 83     }
 84     else if(t == 0){        //唯一解
 85         int ans = 0;
 86         for(int i = 0; i < N*N; i++){
 87             ans += x[i];
 88         }
 89         printf("%d\n", ans);
 90         return;
 91     }
 92     else{                   //多解,需要枚举自由元
 93         int ans = INF;
 94         int tot = 1<<t;
 95         int cnt = 0;
 96         for(int i = 0; i < tot; i++){
 97             cnt = 0;
 98             for(int j = 0; j < t; j++){
 99                 if(i&(1<<j)){
100                     x[free_x[j]] = 1;
101                     cnt++;
102                 }
103                 else x[free_x[j]] = 0;
104             }
105
106             for(int j = var-t-1; j >= 0; j--){
107                 int index;
108                 for(index = j; index < var; index++){
109                     if(a[j][index]) break;
110                 }
111                 x[index] = a[j][var];
112
113                 for(int s = index+1; s < var; s++)
114                 if(a[j][s]) x[index] ^= x[s];
115
116                 cnt+=x[index];
117             }
118             ans = min(ans, cnt);
119         }
120         printf("%d\n", ans);
121     }
122 }
123
124 int main()
125 {
126     int T_case;
127     int tpx, tpy;
128     scanf("%d", &T_case);
129     while(T_case--){
130         scanf("%d", &N);
131         init();
132         for(int i = 0; i < N; i++){
133             scanf("%s", str[i]);
134             for(int j = 0; j < N; j++){
135                 tpx = i*N+j, tpy = N*N;
136                 if(str[i][j] == ‘y‘) a[tpx][tpy] = 0;
137                 else a[tpx][tpy] = 1;
138             }
139         }
140         solve();
141     }
142     return 0;
143 }

POJ 1681 Painter's Problem 【高斯消元 二进制枚举】

原文地址:https://www.cnblogs.com/ymzjj/p/9973367.html

时间: 2024-12-29 11:21:44

POJ 1681 Painter's Problem 【高斯消元 二进制枚举】的相关文章

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 &

【POJ1681】Painter&#39;s Problem 高斯消元,求最小∑系数的异或方程组

#include <stdio.h> int main() { puts("转载请注明出处[vmurder]谢谢"); puts("网址:blog.csdn.net/vmurder/article/details/43483547"); } -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 题意: 多组数据. 有个n*n的正方形,然后你要对某些位置进行操作,使得最后灯的状态都变成y.

POJ 1222【异或高斯消元|二进制状态枚举】

题目链接:[http://poj.org/problem?id=1222] 题意:Light Out,给出一个5 * 6的0,1矩阵,0表示灯熄灭,反之为灯亮.输出一种方案,使得所有的等都被熄灭. 题解:首先可以用高斯消元来做,对于每个点,我们列出一个方程,左边是某个点和它相邻的点,他们的异或值等于右边的值(灯亮为1 ,灯灭为0),然后求一个异或高斯消元就可以了.可以用bitset优化,或者__int128优化(其实unsigned就可以了). 还可以枚举第一行的按开关的状态共有1<<6中状态

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 (高斯消元)

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

poj1681--Painter&#39;s Problem(高斯消元问题4)

Painter's Problem Time Limit:1000MS     Memory Limit:10000KB     64bit IO Format:%I64d & %I64u Submit Status 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 pai

POJ 1753 Flip Game (高斯消元 枚举自由变元求最小步数)

题目链接 题意:4*4的黑白棋,求把棋全变白或者全变黑的最小步数. 分析:以前用状态压缩做过. 和上题差不多,唯一的不同是这个终态是黑棋或者白棋, 但是只需要把给的初态做不同的两次处理就行了. 感觉现在还只是会套模板,不能独立的思考,好伤心.... 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <cmath&g

POJ 2947 Widget Factory (高斯消元 判多解 无解 和解集 模7情况)

题目链接 题意: 公司被吞并,老员工几乎全部被炒鱿鱼.一共有n种不同的工具,编号1-N(代码中是0—N-1), 每种工具的加工时间为3—9天 ,但是现在老员工不在我们不知道每种工具的加工时间,庆幸的是还保留着一些对工人制造工具的记录,对于每个老员工,他的记录包括,他开始工作的时间(在某个星期的星期几),被炒鱿鱼的时间(某个星期的星期几),在第几个星期不知道.....在这段时间里,他正好加工了k件物品,给出了这k件物品的编号.我们要做的就是通过这些记录,来确定每种工具的加工时间是多少. 分析: 对

POJ 1222 extended lights out 高斯消元 板子题

题目链接:http://poj.org/problem?id=1222 题目描述:其实就是开关问题, 按下按钮会影响当前和周围的四个按钮, 问关闭所有灯的方案 解题思路:以前用搜索做过, 那时候是刚刚接触ACM的时候, 当时劲头真足啊, 这个解释的很好:http://blog.csdn.net/u013508213/article/details/47263183 代码: #include <iostream> #include <cstdio> #include <cstr