Luogu【P3609】蹄子剪刀布(DP+滚动数组)
(突然高兴
又一次瞬间想出转移方程并一遍A掉!!233333(虽然从二叉苹果树那题开始我就发现我的方程好像跟别人不大一样
(所以这样就可以名正言顺的水题解了
设f[i][j][k]表示考虑FJ出的前i个手势,Bessie变了j次之后,用k表示的手势到目前为止赢了FJ的最多次数。
则考虑FJ出的第i个手势,有两种情况:
1.Bessie懒得变手势并秒杀FJ。
2.Bessie从石头剪刀布变到了胜利手势并秒杀FJ。
所以状态转移方程比较好想了。
然而f[100000][20][3]=f[6000000]=内存超级大
所以我用了滚动数组。只存上一个状态就可以了。
代码如下
#include<cstdio> #include<cctype> #include<algorithm> #include<cstring> using namespace std; inline long long max(long long a,long long b){ return a>b?a:b; } inline long long read(){ long long num=0,f=1; char ch=getchar(); while(!isdigit(ch)){ if(ch=='-') f=-1; ch=getchar(); } while(isdigit(ch)){ num=num*10+ch-'0'; ch=getchar(); } return num*f; } int f[3][25][5]; int main(){ int n=read(),k=read(); for(int i=1;i<=n;++i){ char cc[10]; int opt; scanf("%s",cc); char c=cc[0]; if(c=='H') opt=1; else if(c=='S') opt=2; else opt=3; int t=opt-1; if(t==0) t=3; for(int j=0;j<=k;++j){ f[2][j][t]=f[1][j][t]; for(int l=1;l<=3;++l) if(f[2][j][t]<f[1][j-1][l]) f[2][j][t]=f[1][j-1][l]; f[2][j][t]++; } for(int j=0;j<=k;++j) for(int l=1;l<=3;++l){ if(f[2][j][l]) f[1][j][l]=f[2][j][l]; f[2][j][l]=0; } } int ans=f[1][k][1]; if(ans<f[1][k][2]) ans=f[1][k][2]; if(ans<f[1][k][3]) ans=f[1][k][3]; printf("%d",ans); return 0; }