POJ 1681 Painter's Problem 【高斯消元 二进制枚举】
任意门:http://poj.org/problem?id=1681
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 7667 | Accepted: 3624 |
Description

Input
Output
Sample Input
2
3
yyy
yyy
yyy
5
wwwww
wwwww
wwwww
wwwww
wwwww
Sample Output
0
15
Source
题意概括:
一个二维矩阵, 输入每个格子的初始颜色,可以进行的操作是 粉刷一个格子则相邻的上下左右四个各自颜色都会取反(只有两种颜色);
问最后把全部各自涂成黄色的最小操作数;
解题思路:
根据题意,每个各自都是一个变元,根据各自之间的相邻关系构造增广矩阵;
高斯消元求出自由元个数 sum;
二进制枚举方案,找出最小的操作数;
AC code:
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#define INF 0x3f3f3f3f
#define LL long long
using namespace std;
const int MAXN = ; int equ, var;
int a[MAXN][MAXN];
char str[MAXN][MAXN];
int x[MAXN];
int free_x[MAXN];
int free_num;
int N; int Gauss()
{
int maxRow, col, k;
free_num = ;
for(k = , col = ; k < equ && col < var; k++, col++){
maxRow = k;
for(int i = k+; i <equ; i++){
if(abs(a[i][col]) > abs(a[maxRow][col]))
maxRow = i;
}
if(a[maxRow][col] == ){ //最大的都为0说明该列下面全是 0
k--;
free_x[free_num++] = col; //说明col是自由元
continue;
}
if(maxRow != k){ //交换行
for(int j = col; j < var+; j++)
swap(a[k][j], a[maxRow][j]);
}
for(int i = k+; i < equ; i++){ //消元
if(a[i][col] != ){
for(int j = col; j < var+; j++){
a[i][j] ^= a[k][j];
}
}
}
}
for(int i = k; i< equ; i++){
if(a[i][col] != ) return -; //无解
}
if(k < var) return var-k; //返回自由元个数 for(int i = var-; i >= ; i--){ //唯一解,回代
x[i] = a[i][var];
for(int j = i+; j < var; j++){
x[i] ^= (a[i][j] && x[j]);
}
}
return ;
} void init()
{
memset(a, , sizeof(a));
memset(x, , sizeof(x));
equ = N*N;
var = N*N;
for(int i = ; i < N; i++){ //构造增广矩阵
for(int j = -; j < N; j++){
int t = i*N+j;
a[t][t] = ;
if(i > ) a[(i-)*N+j][t] = ;
if(i < N-) a[(i+)*N+j][t] = ;
if(j > ) a[i*N+j-][t] = ;
if(j < N-) a[i*N+j+][t] = ;
}
}
} void solve()
{
int t = Gauss();
if(t == -){ //无解
printf("inf\n");
return;
}
else if(t == ){ //唯一解
int ans = ;
for(int i = ; i < N*N; i++){
ans += x[i];
}
printf("%d\n", ans);
return;
}
else{ //多解,需要枚举自由元
int ans = INF;
int tot = <<t;
int cnt = ;
for(int i = ; i < tot; i++){
cnt = ;
for(int j = ; j < t; j++){
if(i&(<<j)){
x[free_x[j]] = ;
cnt++;
}
else x[free_x[j]] = ;
} for(int j = var-t-; j >= ; j--){
int index;
for(index = j; index < var; index++){
if(a[j][index]) break;
}
x[index] = a[j][var]; for(int s = index+; s < var; s++)
if(a[j][s]) x[index] ^= x[s]; cnt+=x[index];
}
ans = min(ans, cnt);
}
printf("%d\n", ans);
}
} int main()
{
int T_case;
int tpx, tpy;
scanf("%d", &T_case);
while(T_case--){
scanf("%d", &N);
init();
for(int i = ; i < N; i++){
scanf("%s", str[i]);
for(int j = ; j < N; j++){
tpx = i*N+j, tpy = N*N;
if(str[i][j] == 'y') a[tpx][tpy] = ;
else a[tpx][tpy] = ;
}
}
solve();
}
return ;
}
POJ 1681 Painter's Problem 【高斯消元 二进制枚举】的更多相关文章
- POJ 1681 Painter's Problem (高斯消元)
题目链接 题意:有一面墙每个格子有黄白两种颜色,刷墙每次刷一格会将上下左右中五个格子变色,求最少的刷方法使得所有的格子都变成yellow. 题解:通过打表我们可以得知4*4的一共有4个自由变元,那么我 ...
- POJ 1681 Painter's Problem [高斯消元XOR]
同上题 需要判断无解 需要求最小按几次,正确做法是枚举自由元的所有取值来遍历变量的所有取值取合法的最小值,然而听说数据太弱自由元全0就可以就水过去吧.... #include <iostream ...
- POJ 1222【异或高斯消元|二进制状态枚举】
题目链接:[http://poj.org/problem?id=1222] 题意:Light Out,给出一个5 * 6的0,1矩阵,0表示灯熄灭,反之为灯亮.输出一种方案,使得所有的等都被熄灭. 题 ...
- POJ 1681 Painter's Problem(高斯消元+枚举自由变元)
http://poj.org/problem?id=1681 题意:有一块只有黄白颜色的n*n的板子,每次刷一块格子时,上下左右都会改变颜色,求最少刷几次可以使得全部变成黄色. 思路: 这道题目也就是 ...
- poj 1681 Painter's Problem(高斯消元)
id=1681">http://poj.org/problem? id=1681 求最少经过的步数使得输入的矩阵全变为y. 思路:高斯消元求出自由变元.然后枚举自由变元,求出最优值. ...
- poj 1681 Painter's Problem
Painter's Problem 题意:给一个n*n(1 <= n <= 15)具有初始颜色(颜色只有yellow&white两种,即01矩阵)的square染色,每次对一个方格 ...
- POJ 2947 Widget Factory(高斯消元)
Description The widget factory produces several different kinds of widgets. Each widget is carefully ...
- POJ 1830 开关问题(高斯消元)题解
思路:乍一看好像和线性代数没什么关系.我们用一个数组B表示第i个位置的灯变了没有,然后假设我用u[i] = 1表示动开关i,mp[i][j] = 1表示动了i之后j也会跟着动,那么第i个开关的最终状态 ...
- POJ 1830 开关问题(高斯消元求解的情况)
开关问题 Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 8714 Accepted: 3424 Description ...
随机推荐
- MySQL 常用show 语句
1. show tables或show tables from database_name; -- 显示当前数据库中所有表的名称. 2. show databases; -- 显示mysql中所有数据 ...
- [Modelsim] 仿真的基本操作
切换路径,建立库并编译所有源文件之后, 键入命令: vopt +acc topmodulename -o top vsim top 其中topmodulename是顶层模块的名称.
- Oracle11gExpress和PL/SQL Developer安装
Oracle11g为64位版本,PL/SQL Developer为32位版本 1.安装64为Oracle数据库/ 适用于 Microsoft Windows (x64) 的 Oracle Databa ...
- spring mvc 外键允许Null
spring mvc 定义模型外键时允许为Null 新手记录,习惯定义模型时将外键的数据类型为long,基本类型. 这样生成的外键是不允许为Null,但是可以通过设置字段的Column注解,使之允许为 ...
- Java简单验证码原理(源代码+步骤操作)
本文章一共分为五个步骤,具体操作流程如下: 一.新建名为:CheckCodeServlet的servlet类; 二.复制以下代码到新建的CheckCodeServlet类中,修改自己的包名: pack ...
- PHP常用数组操作方法汇总
array_change_key_case -- 返回字符串键名全为小写或大写的数组array_chunk -- 将一个数组分割成多个array_combine -- 创建一个数组,用一个数组的值作为 ...
- flutter initializing gradle终极解决方案
自己开发的公众号,可以领取淘宝内部优惠券 修改flutter.gradle文件 这种做法网上一大堆的教程,如果你还没改过建议先试下,比如这篇 Flutter 运行 一直Initializing gra ...
- Java日志框架解析及实战分析
转载自: https://zhuanlan.zhihu.com/p/24272450 https://zhuanlan.zhihu.com/p/24275518 作为Java程序员,幸运的是,Java ...
- String方法使用示例
import java.lang.String; public class StringMethodDemo1{ /** 熟悉String的常用方法. */ public static void ma ...
- PAT 1051 Pop Sequence
#include <cstdio> #include <cstdlib> #include <vector> using namespace std; bool p ...