poj 1681 Painter's Problem
题意:给一个n*n(1 <= n <= 15)具有初始颜色(颜色只有yellow&white两种,即01矩阵)的square染色,每次对一个方格染成黄色时,同时会把周围的方格也染成黄色。(这和1222的开关一样的关联关系)问最后可以将square全部染成黄色的最小染色方格数?
思路:
1.直接预处理出增广矩阵,和1222不同的是里面有最优解的条件,贪心的思想是把自由变元看成是没染色的,但是其他非自由变元(除去自由维度之外的变量)是可以通过自由变元的取值来确定的(在poj 1753中WA了很久,有是一个坑), 但是这道题确实可以不用枚举过。。
2.本题的var = 15*15,变量的个数很大,直接枚举自由变元会不会导致枚举TLE?或者二进制枚举爆数位?这就转化为了方程自由变元的最大个数?如果只考虑高斯消元的全部变量,虽然可以从之间的关联来看会极大的减小自由度,却依旧难证明。但是如果从枚举第一行,就可以递推出全部结果就知道其实是一个一维的自由度,不超过15~~
code1:直接将自由元看成0...(也能A,不够严谨)0ms..
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<map>
#include<queue>
#include<vector>
#include<cmath>
#include<stdlib.h>
#include<time.h>
using namespace std;
#define rep0(i,l,r) for(int i = (l);i < (r);i++)
#define rep1(i,l,r) for(int i = (l);i <= (r);i++)
#define rep_0(i,r,l) for(int i = (r);i > (l);i--)
#define rep_1(i,r,l) for(int i = (r);i >= (l);i--)
#define MS0(a) memset(a,0,sizeof(a))
#define MS1(a) memset(a,-1,sizeof(a)) int dir[][] = {{,,,-},{,,-,}};
int a[][];
int equ,var;
int x[],free_var[];
void debug()
{
puts("********");
int i,j;
rep0(i,,equ){
rep1(j,,var)
cout<<a[i][j]<<" ";
cout<<endl;
}puts("********");
}
int Guass()
{
int i,j,k,row,col,cnt = ;
for(row = ,col = ;row < equ && col < var;row++,col++){
int mx = row;
rep0(j,row+,equ)
if(abs(a[j][col]) > abs(a[mx][col])) mx = j;
if(a[mx][col] == ){
row--; // 行不变;不能通过这里记录自由变元的个数,只能记录没用的col
free_var[col] = ++cnt;//记录自由变元的标号;
continue;
}
if(mx != row)
rep1(k,col,var)
swap(a[row][k],a[mx][k]);
rep0(j,row+,equ){
if(a[j][col]){
rep1(k,col,var)
a[j][k] ^= a[row][k];
}
}
}
//debug();
int use_equ = row; //有用的方程数即能确定的变元的个数
rep0(i,use_equ,equ)
if(a[i][var] != ) return -; //无解
//if(use_equ < var) return var - use_equ;//row表示有用的方程数方程,但是要在判断出有解的前提下才能说有多组解;
rep_1(i,use_equ-,){
x[i] = a[i][var];
rep0(j,i+,use_equ)
x[i] ^= (a[i][j] && x[j]); //第j个灯会影响到第i盏灯,同时第j盏灯也会亮
}
}
void init(int n)
{
int i,j,k;
rep0(i,,n)
rep0(j,,n){
int id = i*n+j;
a[id][id] = ;
rep0(k,,){
int nx = i + dir[][k] ,ny = j + dir[][k];
if(nx < || nx >= n || ny < || ny >= n) continue;
a[nx*n+ny][id] = ;
}
}
}
int main()
{
int T,n,i;
cin>>T;
while(T--){
MS0(x);MS0(a);MS0(free_var);
scanf("%d",&n);
equ = var = n*n ;
rep0(i,,var){
char c = getchar();
if(c == 'w') a[i][var] = ;
else if(c == 'y') a[i][var] = ;
else i--;
}
init(n);
int ret = Guass();
if(ret == -) puts("inf");
else{
int ans = ;
rep0(i,,var)if(free_var[i] == )
ans += x[i];
printf("%d\n",ans);
}
}
return ;
}
code2:枚举自由变元:(16ms)
注意:含有自由变元的式子也是等式。。就是指开始枚举出了自由变量的个数,在后面会不会重复计算。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<map>
#include<queue>
#include<vector>
#include<cmath>
#include<stdlib.h>
#include<time.h>
using namespace std;
#define rep0(i,l,r) for(int i = (l);i < (r);i++)
#define rep1(i,l,r) for(int i = (l);i <= (r);i++)
#define rep_0(i,r,l) for(int i = (r);i > (l);i--)
#define rep_1(i,r,l) for(int i = (r);i >= (l);i--)
#define MS0(a) memset(a,0,sizeof(a))
#define MS1(a) memset(a,-1,sizeof(a))
#define inf 0x3f3f3f3f
int dir[][] = {{,,,-},{,,-,}};
int a[][];
int equ,var;
int x[],free_var[];
void debug()
{
puts("********");
int i,j;
rep0(i,,equ){
rep1(j,,var)
cout<<a[i][j]<<" ";
cout<<endl;
}puts("********");
}
int Guass()
{
int i,j,k,row,col,cnt = ;
for(row = ,col = ;row < equ && col < var;row++,col++){
int mx = row;
rep0(j,row+,equ)
if(abs(a[j][col]) > abs(a[mx][col])) mx = j;
if(a[mx][col] == ){
row--; // 行不变;不能通过这里记录自由变元的个数,只能记录没用的col
free_var[cnt++] = col;//记录自由变元的标号;
continue;
}
if(mx != row)
rep1(k,col,var)
swap(a[row][k],a[mx][k]);
rep0(j,row+,equ){
if(a[j][col]){
rep1(k,col,var)
a[j][k] ^= a[row][k];
}
}
}
//debug();
//row即为有用的方程数即能确定的变元的个数
rep0(i,row,equ)
if(a[i][var] != ) return -; //无解
//枚举自由变元,row表示有用的方程数方程,但是要在判断出有解的前提下才能说有多组解;
//if(row < var) return var - row; //当不需要枚举时,直接返回自由变元的个数
int ans = inf,tot = <<(var - row);
rep0(i,,tot){
int cnt = ,tmp = i;
rep0(j,,var - row){
x[free_var[j]] = (tmp&);
if(x[free_var[j]]) cnt++;//**
tmp >>= ;
}
rep_1(i,row-,){ //自由变元不会相互影响,所以可以不分
x[i] = a[i][var];//现在赋为a[i][var],若为自由变元之后还是会等于0,不会重复计算;
rep0(j,i+,equ){
x[i] ^= (a[i][j] && x[j]); //第j个灯会影响到第i盏灯,同时第j盏灯也会亮
}
if(x[i]) cnt++;
}
ans = min(ans,cnt);
}
return ans;
}
void init(int n)
{
int i,j,k;
rep0(i,,n)
rep0(j,,n){
int id = i*n+j;
a[id][id] = ;
rep0(k,,){
int nx = i + dir[][k] ,ny = j + dir[][k];
if(nx < || nx >= n || ny < || ny >= n) continue;
a[nx*n+ny][id] = ;
}
}
}
int main()
{
int T,n,i;
cin>>T;
while(T--){
MS0(x);MS0(a);MS0(free_var);
scanf("%d",&n);
equ = var = n*n ;
rep0(i,,var){
char c = getchar();
if(c == 'w') a[i][var] = ;
else if(c == 'y') a[i][var] = ;
else i--;
}
init(n);
int ret = Guass();
if(ret == -) puts("inf");
else printf("%d\n",ret);
}
return ;
}
poj 1681 Painter's Problem的更多相关文章
- POJ 1681 Painter's Problem 【高斯消元 二进制枚举】
任意门:http://poj.org/problem?id=1681 Painter's Problem Time Limit: 1000MS Memory Limit: 10000K Total ...
- OpenJudge 2813 画家问题 / Poj 1681 Painter's Problem
1.链接地址: http://bailian.openjudge.cn/practice/2813 http://poj.org/problem?id=1681 2.题目: 总时间限制: 1000ms ...
- POJ 1681 Painter's Problem(高斯消元+枚举自由变元)
http://poj.org/problem?id=1681 题意:有一块只有黄白颜色的n*n的板子,每次刷一块格子时,上下左右都会改变颜色,求最少刷几次可以使得全部变成黄色. 思路: 这道题目也就是 ...
- POJ 1681 Painter's Problem (高斯消元)
题目链接 题意:有一面墙每个格子有黄白两种颜色,刷墙每次刷一格会将上下左右中五个格子变色,求最少的刷方法使得所有的格子都变成yellow. 题解:通过打表我们可以得知4*4的一共有4个自由变元,那么我 ...
- POJ 1681 Painter's Problem (高斯消元 枚举自由变元求最小的步数)
题目链接 题意: 一个n*n 的木板 ,每个格子 都 可以 染成 白色和黄色,( 一旦我们对也个格子染色 ,他的上下左右 都将改变颜色): 给定一个初始状态 , 求将 所有的 格子 染成黄色 最少需要 ...
- POJ 1681 Painter's Problem [高斯消元XOR]
同上题 需要判断无解 需要求最小按几次,正确做法是枚举自由元的所有取值来遍历变量的所有取值取合法的最小值,然而听说数据太弱自由元全0就可以就水过去吧.... #include <iostream ...
- poj 1681 Painter's Problem(高斯消元)
id=1681">http://poj.org/problem? id=1681 求最少经过的步数使得输入的矩阵全变为y. 思路:高斯消元求出自由变元.然后枚举自由变元,求出最优值. ...
- POJ 1222 POJ 1830 POJ 1681 POJ 1753 POJ 3185 高斯消元求解一类开关问题
http://poj.org/problem?id=1222 http://poj.org/problem?id=1830 http://poj.org/problem?id=1681 http:// ...
- Painter's Problem (高斯消元)
There is a square wall which is made of n*n small square bricks. Some bricks are white while some br ...
随机推荐
- AndroidPN中的心跳检测
在AndroidPN客户端里存在着心跳检测功能.就是每隔一段时间客户端向服务器端发送一个消息,以检测连接是否正常,发送的消息内容为: <presence id="h09Ke-13&qu ...
- 开发XMPP IM
Openfire 是一个用Java 实现的XMPP 服务器,客户端可以通过IQ的方式与其进行通信(其实就是XML),客户端和服务器之间的通信是依靠底层Smack 库提供的各种功能来完成的.其实利用插件 ...
- struts2 struts.xml配置文件详解
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN&quo ...
- How to Enable Multi-Touch
This is a frequently asked question. Multi-touch feature is available on both iOS & Android port ...
- 正确的使用枚举(Enum)
状态与选项的区别(states and options) 在用enum之前,我个人觉得,区分一下状态和选项的概念还是很必要的. 状态,同时只能有一种,如“OK”,“Error”,不可能同时是OK和Er ...
- 关于Intent的七大属性
原谅我愚昧,Intent七大属性这个概念我也是昨天才接触到,看了一下,都是一些常用的东西,就是没有总结过,那么今天就来简单总结一下. Intent七大属性是指Intent的ComponentName. ...
- chrome浏览器频频崩溃,如何解决?
之前chrome常崩溃,也没有找到原因,就将就着用吧,一直用到今天, 今天连续几次崩了,突然想到,难道是因为我访问的域名没有解析(能想到这个,是因为今天分配公司域名测试的时候常输错),于是就输入一个不 ...
- Android(java)学习笔记164:Relativelayout相对布局案例
我们看看案例代码,自己心领神会: <?xml version="1.0" encoding="utf-8"?> <RelativeLayout ...
- PHP中的超级全局变量
PHP内置了一些超级全局变量,我们可以在脚本的任何地方使用和可见,下面记录一下这些全局变量的作用: 1.$_SERVER $_SERVER超级全局变量包含由web服务器创建的信息,它提供了服务器和客户 ...
- Asp.net上传出现“超过了最大请求长度”的问题解决方法
在开发ASP.NET网站后台管理系统时,我们可能会遇到这样的问题:上传大于4M的文件时,会提示错误:错误信息如下: 1.异常详细信息:超过了最大请求长度. 2.引发异常的方法:Byte[] GetEn ...