【POJ 1681】 Painter's Problem (高斯消元)
2015-10-30 22:11
561 查看
【POJ 1681】 Painter's Problem (高斯消元)
每个小格可以列出一个方程 对于一个格子只受到本身和上下左右共五个格子的影响 同时此格子最终只会是0/1(不翻/翻)以此初始化即可
高斯消元列出n*n个方程求解即可 要注意多解的情况枚举改变不定变元的值 找出翻动的最小步数
代码如下:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
using namespace std;
const int INF = 0x3f3f3f3f;
int a[233][233];
int x[233];
int free_x[233];
int free_num,equ,var;
void init(int n)
{
memset(a,0,sizeof(a));
memset(x,0,sizeof(x));
free_num = 0;
var = equ = n*n;
for(int i = 0; i < n; ++i)
{
for(int j = 0; j < n; ++j)
{
int t = i*n+j;
a[t][t] = 1;
if(i) a[(i-1)*n+j][t] = 1;
if(j) a[i*n+j-1][t] = 1;
if(i < n-1) a[(i+1)*n+j][t] = 1;
if(j < n-1) a[i*n+j+1][t] = 1;
}
}
}
int Gauss()
{
int k,col;
for(k = col = 0; k < equ && col < var; ++k, ++col)
{
int mx = k;
for(int i = k+1; i < equ; ++i)
{
if(abs(a[i][col]) > abs(a[mx][col])) mx = i;
}
if(!a[mx][col])
{
--k;
free_x[free_num++] = col;
continue;
}
if(mx != k)
{
for(int i = col; i <= var; ++i)
swap(a[k][i],a[mx][i]);
}
for(int i = k+1; 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][var]) return -1;
if(k < var) return var-k;
for(int i = var-1; ~i; --i)
{
x[i] = a[i][var];
for(int j = i+1; j < var; ++j)
x[i] ^= (a[i][j]&&x[j]);
}
return 0;
}
void solve()
{
int ans,cnt,id;
int t = Gauss();
if(t == -1) puts("inf");
else if(!t)
{
ans = 0;
for(int i = 0; i < var; ++i) ans += x[i];
printf("%d\n",ans);
}
else
{
ans = INF;
int tot = (1<<t);
for(int i = 0; i < tot; ++i)
{
cnt = 0;
for(int j = 0; j < t; ++j)
{
if(i&(1<<j))
{
x[free_x[j]] = 1;
cnt++;
}
else x[free_x[j]] = 0;
}
for(int j = var-t-1; ~j; --j)
{
for(id = j; id < var; ++id)
if(a[j][id]) break;
x[id] = a[j][var];
for(int k = id+1; k <var; ++k)
if(a[j][k]) x[id] ^= x[k];
cnt += x[id];
}
ans = min(ans,cnt);
}
printf("%d\n",ans);
}
}
int main()
{
char str[33];
int t,n;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
init(n);
for(int i = 0; i < n; ++i)
{
scanf("%s",str);
for(int j = 0; j < n; ++j)
{
if(str[j] == 'w') a[i*n+j][var] = 1;
else a[i*n+j][var] = 0;
}
}
solve();
}
return 0;
}
Painter's Problem
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 张嘉龄 |
高斯消元列出n*n个方程求解即可 要注意多解的情况枚举改变不定变元的值 找出翻动的最小步数
代码如下:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
using namespace std;
const int INF = 0x3f3f3f3f;
int a[233][233];
int x[233];
int free_x[233];
int free_num,equ,var;
void init(int n)
{
memset(a,0,sizeof(a));
memset(x,0,sizeof(x));
free_num = 0;
var = equ = n*n;
for(int i = 0; i < n; ++i)
{
for(int j = 0; j < n; ++j)
{
int t = i*n+j;
a[t][t] = 1;
if(i) a[(i-1)*n+j][t] = 1;
if(j) a[i*n+j-1][t] = 1;
if(i < n-1) a[(i+1)*n+j][t] = 1;
if(j < n-1) a[i*n+j+1][t] = 1;
}
}
}
int Gauss()
{
int k,col;
for(k = col = 0; k < equ && col < var; ++k, ++col)
{
int mx = k;
for(int i = k+1; i < equ; ++i)
{
if(abs(a[i][col]) > abs(a[mx][col])) mx = i;
}
if(!a[mx][col])
{
--k;
free_x[free_num++] = col;
continue;
}
if(mx != k)
{
for(int i = col; i <= var; ++i)
swap(a[k][i],a[mx][i]);
}
for(int i = k+1; 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][var]) return -1;
if(k < var) return var-k;
for(int i = var-1; ~i; --i)
{
x[i] = a[i][var];
for(int j = i+1; j < var; ++j)
x[i] ^= (a[i][j]&&x[j]);
}
return 0;
}
void solve()
{
int ans,cnt,id;
int t = Gauss();
if(t == -1) puts("inf");
else if(!t)
{
ans = 0;
for(int i = 0; i < var; ++i) ans += x[i];
printf("%d\n",ans);
}
else
{
ans = INF;
int tot = (1<<t);
for(int i = 0; i < tot; ++i)
{
cnt = 0;
for(int j = 0; j < t; ++j)
{
if(i&(1<<j))
{
x[free_x[j]] = 1;
cnt++;
}
else x[free_x[j]] = 0;
}
for(int j = var-t-1; ~j; --j)
{
for(id = j; id < var; ++id)
if(a[j][id]) break;
x[id] = a[j][var];
for(int k = id+1; k <var; ++k)
if(a[j][k]) x[id] ^= x[k];
cnt += x[id];
}
ans = min(ans,cnt);
}
printf("%d\n",ans);
}
}
int main()
{
char str[33];
int t,n;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
init(n);
for(int i = 0; i < n; ++i)
{
scanf("%s",str);
for(int j = 0; j < n; ++j)
{
if(str[j] == 'w') a[i*n+j][var] = 1;
else a[i*n+j][var] = 0;
}
}
solve();
}
return 0;
}
相关文章推荐
- VS2012工程用2010打不开的以及error LNK1123: failure during conversion to COFF的解决方案
- sicily 1193. Up the Stairs
- AIR文件操作:使用文件对象操作文件和目录 .
- multithreading--synchronized对象锁以及对象的notify(),notifyAll(),wait()等的用法
- sicily 1093. Air Express
- H - Relief grain
- 线程的sleep()和wait() 区别
- 给hmailserver添加SSL支持
- SendMail
- HDU 4300 Clairewd’s message (kmp | exkmp)
- 通过CONSTRAINTS查看表之间的主外键关系
- STM_HAL: assert_param 与 assert_failed函数
- BZOJ 4320 ShangHai2006 Homework 并查集
- OS X EI Captain安装Cocoapods问题
- Aizu-0558 Cheese
- bzoj-1535 Sza-Template
- Aizu-0033 Ball
- ORA-00054 资源正忙, 但指定以 NOWAIT 方式获取资源, 或者超时失效"的快速解决方法
- 如何签名apk,并让baidu地图正常显示
- Fail to connect to camera service的几种原因和解决方法