BZOJ1802: [Ahoi2009]checker
这种需要手玩/多考虑几种情况的题不手玩不好好考虑就只有 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; }
禁止诸如开发者知识库/布布扣/码迷/学步园/马开东等 copy 他人博文乃至博客的网站转载
,用户转载请注明出处:https://www.cnblogs.com/xcysblog/