您的位置:首页 > 其它

poj 3185 The Water Bowls(数学:高斯消元)

2014-11-22 15:01 567 查看
每个位置只影响相邻位置

做高斯消元之后再枚举即可

代码如下:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAXN 50
using namespace std;

int x[MAXN];
int free_x[MAXN];
int a[MAXN][MAXN];

void print() {
for(int i=0; i<20; ++i) {
for(int j=0; j<=20; ++j)
printf("%d ", a[i][j]);
puts("");
}
}

int gauss(int equ, int var) {
int i, j, k, col;
int ta, tb, LCM;
int tmp, free_index;
int free_x_num, max_r;

int num = 0;
for(int i=0; i<=var; ++i) {
x[i] = 0;
free_x[i] = 0;
}

col = 0;
for(k=0; k<equ&&col<var; ++k, ++col) {
max_r = k;
for(i=k+1; i<equ; ++i) {
if(abs(a[i][col]) > abs(a[max_r][col]))
max_r = i;
}
if(max_r != k)
for(j=k; j<=var; ++j)
swap(a[k][j], a[max_r][j]);
if(a[k][col] == 0) {
--k;
free_x[num++] = col;
continue;
}
for(i=k+1; i<equ; ++i) {
if(a[i][col]) {
for(j=col; j<=var; ++j)
a[i][j] ^= a[k][j];
}
}
}
for(i=k; i<equ; ++i) {
if(a[i][col]) return -1;
}
return var-k;
}

void solve(int equ, int var) {
int ans = gauss(equ, var);
if(ans == 0) {
int res = 0;
for(int i=0; i<equ; ++i)
res += x[i];
printf("%d\n", res);
return ;
} else {
int res = 0x3f3f3f3f;
int tot = (1<<ans);
for(int i=0; i<tot; ++i) {
int cnt = 0;
for(int j=0; j<ans; ++j) {
if(i&(1<<j)) {
x[free_x[j]] = 1;
++cnt;
} else x[free_x[j]] = 0;
}
for(int j=var-ans-1; j>=0; --j) {
int tmp = a[j][var];
for(int l=j+1; l<var; ++l)
if(a[j][l])
tmp ^= x[l];
x[j] = tmp;
if(x[j]) ++cnt;
}
res = min(res, cnt);
}
printf("%d\n", res);
}
}

int main(void) {
int nx;
while(~scanf("%d", &nx)) {
memset(a, 0, sizeof(a));
a[0][20] = nx;
for(int i=1; i<20; ++i)
scanf("%d", &a[i][20]);

a[0][0] = a[0][1] = 1;
a[19][18] = a[19][19] = 1;
for(int i=1; i<19; ++i) {
a[i][i] = a[i][i-1] = a[i][i+1] = 1;
}
//print();
solve(20, 20);
//print();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: