题目描述见链接 .
设 表示送完第 次餐车, 第一个矿坑使用的最后两个元素为 , 第二个矿坑使用的最后两个元素为 所能获得的最优值,
转移很显然:
时间复杂度 .
这道题目卡空间, 需要滚动数组 .
计算答案的函数需要注意不能这么写, 这么写会使得三个相同的情况返回 .
int calc(int a, int b, int c){
if(!a && !b) return 1;
else if(!a) return (b!=c)?2:1;
return (a!=b) + (a!=c) + (b!=c);
}
#include<bits/stdc++.h>
#define reg register
const int maxn = 100005;
int N;
int t1;
int t2;
int Ans;
int Tong[4];
int F[2][4][4][4][4];
char S[maxn];
int Trans(char c){ return (c!='M')?(c!='B'?1:2):3; }
int calc(int a, int b, int c){
int res = 0;
Tong[1] = Tong[2] = Tong[3] = 0;
if(a && (++ Tong[a]) == 1) res ++;
if(b && (++ Tong[b]) == 1) res ++;
if(c && (++ Tong[c]) == 1) res ++;
return res;
}
int main(){
scanf("%d", &N); scanf("%s", S+1);
int cur = 0;
memset(F, -1, sizeof F); F[0][0][0][0][0] = 0;
for(reg int i = 1; i <= N; i ++){
cur ^= 1; memset(F[cur], -1, sizeof F[cur]);
for(reg int a = 0; a <= 3; a ++)
for(reg int b = 0; b <= 3; b ++)
for(reg int c = 0; c <= 3; c ++)
for(reg int d = 0; d <= 3; d ++){
if(F[cur^1][a][b][c][d] == -1) continue ;
int now = Trans(S[i]);
F[cur][now][a][c][d] = std::max(F[cur][now][a][c][d], F[cur^1][a][b][c][d] + calc(b, a, now));
F[cur][a][b][now][c] = std::max(F[cur][a][b][now][c], F[cur^1][a][b][c][d] + calc(d, c, now));
}
}
for(reg int a = 0; a <= 3; a ++)
for(reg int b = 0; b <= 3; b ++)
for(reg int c = 0; c <= 3; c ++)
for(reg int d = 0; d <= 3; d ++) Ans = std::max(Ans, F[cur][a][b][c][d]);
printf("%d
", Ans);
return 0;
}