1. 程式人生 > >BZOJ1802: [Ahoi2009]checker

BZOJ1802: [Ahoi2009]checker

mes 需要 str ns2 tps urn class true 最大

這種需要手玩/多考慮幾種情況的題不手玩不好好考慮就只有 20 tps

主要要考慮到可能會有相鄰的兩個紅格子,
這樣他們倆是可以通過不斷放/跳棋子來 reach 任何一個格子

那之後怎麽求總數?

其實就是 f[i] = f[i - 1] + f[i - 2] / f[i] = f[i + 1] + f[i + 2]

紅色格子 f 值為 1,其余為 INF

由於 1 位置是初始棋子,不能算入

註意最大到 1e15,memset的數小了是會 GG 的


代碼:

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cctype>
using namespace std;

typedef long long ll;
const int MAXN = 1005;

int n;
int seq[MAXN];
ll ans1, ans2;
ll f[MAXN];
bool hasnei;

int main() {
	scanf("%d", &n);
	for (int i = 1; i <= n; ++i)
		scanf("%d", &seq[i]);
	ans1 = (n >> 1);
	for (int i = 2; i < n; i += 2) 
		if (seq[i]) --ans1;
	memset(f, 0x3f, sizeof(f));
	for (int i = 3; i <= n; ++i) {
		if (seq[i - 1] && seq[i]) hasnei = true;
	}
	if (!hasnei) {
		printf("%lld\n%lld\n", ans1, (n >> 1) - ans1);
	} else {
		for (int i = 2; i <= n; ++i) 
			if (seq[i]) f[i] = 1ll;
		ans2 = 0;
		for (int i = 2; i <= n; ++i) {
			f[i] = min(f[i], f[i - 1] + f[i - 2]);
		}
		for (int i = n; i >= 2; --i) {
			f[i] = min(f[i], f[i + 1] + f[i + 2]);
		}
		for (int i = 2; i < n; i += 2) {
			ans2 += f[i];
		}
		printf("0\n%lld\n", ans2);
	}
	return 0;
}

BZOJ1802: [Ahoi2009]checker