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 ...
随机推荐
- linux 运维基础之VM中安装centos6.X
VM中安装centos详细教程 图片讲解:
- ansible 命令详解{图片详解}
本文内容来至于http://www.zsythink.net 文件操作模块 命令操作模块 cron 包管理模块
- git读书笔记以及使用技巧
[添加文件] git add 把文件修改添加到暂存区 git commit -m '' 把暂存区的所有内容提交到当前分支 [查看历史] git log 查看提交历史 git log -- ...
- linux下统计文本行数的各种方法(二)
上一篇讲的都是统计单个文件的方法,直接在命令行执行就可以.现在试试脚本的方式,统计多个文件的行数 一.统计目录下所有文件的文件数及所有行数 脚本暂时命名为count.sh,代码如下: #!/bin/b ...
- 【Elasticsearch】集群管理
8.1 Elasticsearch时光机 Elasticsearch的快照,防止出错,灾备8.1.1 创建快照存储库创建快照之前必须建一个存储库,有如下几个方面,name,type,settings, ...
- jQuery autocomplete 应用
1. 引入css和js <link rel="stylesheet" href="{{ url_for('static', filename='jquery.aut ...
- sql 创建用户脚本
USE master go CREATE LOGIN jiazhuang --用户名 WITH PASSWORD = 'sa', --密码 DEFAULT_DATABASE = JiaZhuan, ...
- 使用vue-router切换页面时,获取上一页url以及当前页面url
今天在实现一个小功能的时候,遇到一个问题,使用vue-router获取上一页面的url信息,我尝试了多种方式,发现使用vue-router的canDeactivate钩子实现这个功能最为方便,现在将我 ...
- PAT 1076 Forwards on Weibo
#include <cstdio> #include <cstdlib> #include <vector> #include <queue> #inc ...
- redux基本使用
redux数据流向 基本使用