五维dp,记忆化搜索会MLE超内存,所以用滚动数组,十分经典
五维dp
#include <bits/stdc++.h> using namespace std; const int maxn=100010; int n,tp[maxn],now[4][4][4][4],last[4][4][4][4]; char s[maxn]; int trans(char c){ if(c=='M')return 1; if(c=='F')return 2; if(c=='B')return 3; return -1; } int judge(int a,int b,int c){ if(!a && !b) return 1; if(!a )return (b!=c)+1; if(a==b && b==c)return 1; return (a!=b)+(b!=c)+(c!=a); } int main(){ //freopen("77.in","r",stdin); //freopen("77.out","w",stdout); scanf("%d",&n); scanf("%s",s); for(int i=1;i<=n;i++) tp[i]=trans(s[i-1]); for(int i=n;i>=1;i--){ memset(now,0,sizeof now); int p1,p2; for(int a1=0;a1<=3;a1++) for(int a2=0;a2<=3;a2++) for(int b1=0;b1<=3;b1++) for(int b2=0;b2<=3;b2++){ p1=judge(a1,a2,tp[i]),p2=judge(b1,b2,tp[i]); now[a1][a2][b1][b2]=max(last[a2][tp[i]][b1][b2]+p1,last[a1][a2][b2][tp[i]]+p2); }swap(now,last); } printf("%d",last[0][0][0][0]); return 0; }
记忆化搜索
#include <iostream> #include <cstdio> using namespace std; const int maxn=100010; int n,tp[maxn],f[maxn][4][4][4][4]; int trans(char c){ if(c=='M')return 1; if(c=='F')return 2; if(c=='B')return 3; return -1; } int judge(int a,int b,int c){ if(!a && !b) return 1; if(!a )return (b!=c)+1; if(a==b && b==c)return 1; return (a!=b)+(b!=c)+(c!=a); } int dp(int now,int a1,int a2,int b1,int b2){ if(now>n) return 0; if(f[now][a1][a2][b1][b2]) return f[now][a1][a2][b1][b2]; f[now][a1][a2][b1][b2]=max( dp(now+1,a2,tp[now],b1,b2)+judge(a1,a2,tp[now]),dp(now+1,a1,a2,b2,tp[now])+judge(b1,b2,tp[now]) ); return f[now][a1][a2][b1][b2]; } char s[maxn]; int main(){ freopen("77.in","r",stdin); freopen("77.out","w",stdout); scanf("%d",&n); scanf("%s",s); for(int i=1;i<=n;i++){ int t=trans(s[i-1]); tp[i]=t; }printf("%d\n",dp(1,0,0,0,0)); return 0; }
用于复习了