POJ 3185 The Water Bowls 翻转计数/异或高斯消元

给定20个桶的状态,可以翻转桶把相邻的状态变换。问最少的变换次数。

此类问题通常有以下解决方案 1.暴力枚举 2.高斯消元 + 暴力枚举 3.找规律性质

这题和上一题POJ1830 很相似,可以用高斯消元异或方程组枚举自由元做。 但是比较麻烦;

注意到每个桶至多翻转一次。  从右往左的第一个1必然要通过 i+1号翻转来实现,因此可以O(n) 贪心 解决。

当然要考虑边界,这里可以加一个虚拟的0号桶。

#pragma warning(disable:4996)

#include<iostream>
#include<algorithm>
#include<bitset>
#include<tuple>
#include<unordered_map>
#include<fstream>
#include<iomanip>
#include<string>
#include<cmath>
#include<cstring>
#include<vector>
#include<map>
#include<set>
#include<list>
#include<queue>
#include<stack>
#include<sstream>
#include<cstdio>
#include<ctime>
#include<cstdlib>
#define INF 0x3f3f3f3f
#define inf 0x7FFFFFFF
#define MOD 998244353
#define moD 1000000003
#define pii pair<int,int>
#define eps 1e-8
#define equals(a,b) (fabs(a-b)<eps)
#define bug puts("bug")
#define re  register
#define fi first
#define se second
const int maxn = 100;
const double Inf = 10000.0;
const double PI = acos(-1.0);
typedef  long long ll;
typedef unsigned long long ull;
using namespace std;

int dir[25];
int dirr[25];


int solve(int sta,int *dir) {
    dir[0] = sta;
    int res = 0;
    for (int i = 0; i <= 19; i++) {
        if (dir[i] == 1) dir[i] = 0, dir[i + 1] ^= 1, dir[i + 2] ^= 1, res++;
    }
    return res;
}

int main() {
    for (int i = 1; i <= 20; i++) scanf("%d", &dir[i]);
    for (int i = 1; i <= 20; i++) dirr[i] = dir[i];
    printf("%d
", min(solve(0, dir), solve(1, dirr)));
}
原文地址:https://www.cnblogs.com/hznumqf/p/13328521.html