题目大意:将一个123序列拆分为两个子序列,定义每个数的贡献值为以这个数结尾的长度最大为3的子串中不同数的数量,求贡献值和的最大值
题解:类似状压的思想,f[i][a1][a2][b1][b2]为前i个数分成两组,第一组以a1a2结尾,第二组以b1b2结尾的最大贡献值
因为有非法情况而且取max,所以要初始值赋成−1……,f[0][0][0][0][0]=0
大力转移即可,需要滚动数组
我的收获:暴力表示状态,考虑状态非法……
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define rec(i) for(int i=0;i<4;i++)
int n,f[2][4][4][4][4];
int p=1,l=0;
inline int cread(){
char c=getchar();
for(;c!='M'&&c!='F'&&c!='B';c=getchar());
if(c=='M') return 1;
if(c=='F') return 2;
if(c=='B') return 3;
}
inline int calc(int a,int b,int c){
int res=1;
if(a!=0&&a!=b&&a!=c) res++;
if(b!=0&&b!=c) res++;
return res;
}
void dp()
{
memset(f,-1,sizeof(f));
f[0][0][0][0][0]=0;
for(int i=1;i<=n;i++,p^=1,l^=1){
int t=cread();
rec(a1) rec(a2) rec(b1) rec(b2){
if(f[l][a1][a2][b1][b2]==-1) continue;
f[p][a2][t][b1][b2]=max(f[p][a2][t][b1][b2],f[l][a1][a2][b1][b2]+calc(a1,a2,t));
f[p][a1][a2][b2][t]=max(f[p][a1][a2][b2][t],f[l][a1][a2][b1][b2]+calc(b1,b2,t));
}
}
}
void work()
{
dp();
int ans=0;
rec(a1) rec(a2) rec(b1) rec(b2)
ans=max(ans,f[l][a1][a2][b1][b2]);
printf("%d\n",ans);
}
void init(){
scanf("%d",&n);
}
int main()
{
init();
work();
return 0;
}