[CF991D]Bishwock_状压dp

Bishwock

题目链接http://codeforces.com/problemset/problem/991/D

数据范围:略。


题解

一眼题。

首先,每个$L$最多只占用两列,而且行数特别少,我们考虑状态压缩。

即$f_{i, S}$表示前$i$列,第$j$列的状态为$S$时,前$j$最多能放多少个。

随便弄一弄就好了。

代码

#include <bits/stdc++.h>

#define setIO(s) freopen(s".in", "r", stdin), freopen(s".out", "w", stdout) 

#define N 100010 

using namespace std;

int f[N][1 << 4], dic[4];

char s[2][N];

int main() {
	// setIO("a");
	scanf("%s%s", s[0] + 1, s[1] + 1);
	int n = strlen(s[0] + 1);
	int all = (1 << 4) - 1;
	for (int i = 0; i < 4; i ++ ) {
		dic[i] = all - (1 << i);
	}
	for (int i = 2; i <= n; i ++ ) {
		int mdl = 0;
		if (s[0][i - 1] == 'X') {
			mdl += 1;
		}
		if (s[1][i - 1] == 'X') {
			mdl += 2;
		}
		if (s[0][i] == 'X') {
			mdl += 4;
		}
		if (s[1][i] == 'X') {
			mdl += 8;
		}
		// cout << mdl << endl ;
		for (int s1 = 0; s1 < (1 << 2); s1 ++ ) {
			for (int s2 = 0; s2 < (1 << 2); s2 ++ ) {
				// i -> s1, i - 1 -> s2
				int tmp = s2 + (s1 << 2), re = all - tmp;
				if ((tmp & mdl) == mdl) {
					f[i][s1] = max(f[i][s1], f[i - 1][s2]);
					for (int k = 0; k < 4; k ++ ) {
						if ((dic[k] & re) == dic[k]) {
							int x = s2;
							if (dic[k] & 1) {
								x ++ ;
							}
							if (dic[k] & 2) {
								x += 2;
							}
							f[i][s1] = max(f[i][s1], f[i - 1][x] + 1);
						}
					}
				}
			}
		}
	}
	int ans = 0;
	for (int i = 0; i <= all; i ++ ) {
		ans = max(ans, f[n][i]);
	}
	cout << ans << endl ;
	fclose(stdin), fclose(stdout);
	return 0;
}

小结:一定要想明白状态再转移。

posted @ 2019-10-24 15:30  JZYshuraK_彧  阅读(194)  评论(2编辑  收藏  举报