题目描述见链接 .
可以发现当有 个连续的红格子出现时, 可以通过这两个红格子将棋子送达每个位置 .
于是先讨论有 个连续红格子的情况, 此时第一问的答案显然为 .
再考虑第二问的答案是什么, 可以预处理出 表示在 位置放置棋子的最小代价,
当 位置是红格子时, , 否则初值 ,
转移 ,
最后把偶数位的答案累计起来即可 .
再讨论没有 个连续红格子的情况, 此时第一问答案显然为偶数位的白格子个数, 第二问答案为偶数位红格子个数 .
总时间复杂度 .
- 注意第一个格子即使是红色的, 也要看成白色, 因为不会在第一个格子上放棋子 .
#include<bits/stdc++.h>
#define reg register
typedef long long ll;
const int maxn = 1005;
const ll inf = 0x3f3f3f3f3f3f3f3f;
int N;
int flag;
int A[maxn];
ll Ans_1;
ll Ans_2;
ll F[maxn];
int main(){
scanf("%d", &N);
memset(F, 0x3f, sizeof F);
for(reg int i = 1; i <= N; i ++){
scanf("%d", &A[i]); F[i] = A[i]?1:inf;
if(i >= 3 && A[i] && A[i-1]) flag = 1;
}
F[1] = inf;
if(!flag){
for(reg int i = 2; i <= N; i += 2)
if(A[i]) Ans_2 ++; else Ans_1 ++;
}else{
F[0] = inf, F[N+1] = inf;
for(reg int i = 1; i <= N; i ++) if(i != 1) F[i] = std::min(F[i], F[i-1]+F[i-2]);
for(reg int i = N; i >= 1; i --) if(i != N) F[i] = std::min(F[i], F[i+1]+F[i+2]);
for(reg int i = 2; i <= N; i += 2) Ans_2 += F[i];
Ans_1 = 0;
}
printf("%lld
%lld
", Ans_1, Ans_2);
return 0;
}