【Luogu】P1410子序列(DP)
我DP是真的菜啊啊啊啊啊!
f[i][j]表示考虑前i个数,有i-j+1个数组成一个上升子序列,且不以i结尾的尾端最小值。
设a为j个数组成的序列,且以i结尾;b为i-j+1个数组成的序列,且不以i结尾。
从f[i][j]到f[i+1][j+1]的转移如下:
若a后面可以接上第i+1个数,那b就和原来一样。也就是f[i+1][j+1]=min(f[i+1][j+1],f[i][j])
如果a后面不能接上第i+1个数,那就接到b上。也就是f[i+1][i-j+1]=min(f[i+1][i-j+1],que[i])
代码奉上
#include<cstdio> #include<cctype> #include<iostream> #include<cstring> using namespace std; 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[2020][2020]; int que[3000]; int n; int main(){ while(~scanf("%d",&n)){ memset(f,127,sizeof(f)); for(int i=1;i<=n;++i) que[i]=read(); f[1][1]=-1; for(int i=1;i<=n;++i) for(int j=1;j<=i;++j) if(f[i][j]!=f[0][0]){ if(que[i]<que[i+1]) f[i+1][j+1]=min(f[i+1][j+1],f[i][j]); if(f[i][j]<que[i+1]) f[i+1][i-j+1]=min(f[i+1][i-j+1],que[i]); } if(f[n][n>>1]==f[0][0]) printf("No!\n"); else printf("Yes!\n"); } return 0; }