BZOJ1802: [Ahoi2009]checker
阿新 • • 發佈:2018-10-22
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