poj 3185 The Water Bowls 高斯消元枚举变元

时间:2023-03-10 01:03:29
poj 3185 The Water Bowls  高斯消元枚举变元

题目链接

给一行0 1 的数, 翻转一个就会使他以及它左右两边的都变, 求最少多少次可以变成全0。

模板题。

#include <iostream>
#include <vector>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <map>
#include <set>
#include <string>
#include <queue>
#include <stack>
#include <bitset>
using namespace std;
#define pb(x) push_back(x)
#define ll long long
#define mk(x, y) make_pair(x, y)
#define lson l, m, rt<<1
#define mem(a) memset(a, 0, sizeof(a))
#define rson m+1, r, rt<<1|1
#define mem1(a) memset(a, -1, sizeof(a))
#define mem2(a) memset(a, 0x3f, sizeof(a))
#define rep(i, n, a) for(int i = a; i<n; i++)
#define fi first
#define se second
typedef pair<int, int> pll;
const double PI = acos(-1.0);
const double eps = 1e-;
const int mod = 1e9+;
const int inf = ;
const int dir[][] = { {-, }, {, }, {, -}, {, } };
int a[][], ans[], x[];
int n, l[], free_x[];
int gauss(int equ,int var)
{
int i,j,k, max_r, col = , temp, free_index, num = ;
for(int i=;i<=var;i++)
{
x[i]=;
free_x[i]=;
}
for(k = ;k < equ && col < var;k++,col++)
{
max_r=k;
for(i=k+;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]==)
{
k--;
free_x[num++]=col;
continue;
}
for(i=k+;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 -;
}
int stat = <<(var-k);
int res = inf;
for(i=;i<stat;i++)
{
int cnt=;
int index=i;
for(j=;j<var-k;j++)
{
x[free_x[j]]=(index&);
if(x[free_x[j]]) cnt++;
index>>=;
}
for(j=k-;j>=;j--)
{
int tmp=a[j][var];
int t=;
while(a[j][t]==)t++;
for(int l=t+;l<var;l++)
if(a[j][l]) tmp^=x[l];
x[t]=tmp;
if(x[t])cnt++;
}
if(cnt<res)res=cnt;
}
return res;
}
int main()
{
for(int i = ; i<; i++) {
scanf("%d", &a[i][]);
}
for(int i = ; i<; i++) {
if(i) {
a[i][i-] = ;
}
if(i!=)
a[i][i+] = ;
a[i][i] = ;
}
int ans = gauss(, );
cout<<ans<<endl;
return ;
}