takapt0226's diary

競技プログラミングのことを書きます

POJ 3185 The Water Bowls

解法

greedy
左端をflipするかの2通りを試す
位置iが1である場合、iをひっくり返すにはi, i + 1, i + 2をひっくり返す必要があるのでgreedyにやる

別解
反転パターンを全探索。bit + 無駄な探索しない高速化をしないとTLEする

ソースコード

greedy

int main()
{
    int b[25] = {};
    rep(i, 20)
	cin >> b[i + 1];

    int res = 3333;
    rep(_, 2)
    {
	int a[25];
	COPY(a, b);
	if (_)
	    a[0] = 1;

	int f = 0;
	rep(i, 20)
	{
	    if (a[i])
	    {
		++f;
		rep(j, 3)
		    a[i + j] ^= 1;
	    }
	}
	if (count(a, a + 21, 1) == 0)
	    chmin(res, f);
    }
    cout << res << endl;
}


全探索

int main()
{
    int b = 0;
    rep(i, 20)
    {
	int f;
	scanf("%d", &f);
	b |= f << i;
    }
    b <<= 1;

    const int rev = (1 << 3) - 1;
    const int filter = ((1 << 20) - 1) << 1;
    int res = 3333;
    rep(s, 1 << 20)
    {
	int flips = __builtin_popcount(s);
	if (flips < res) // 刈る
	{
	    int a = b;
	    rep(i, 20)
		if (s >> i & 1)
		    a ^= rev << i;

	    a &= filter;
	    if (a == 0)
		res = flips;
	}
    }
    printf("%d\n", res);
}