dp(水题大战)
Posted hzoidj123
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了dp(水题大战)相关的知识,希望对你有一定的参考价值。
本题题面有误,所求非递增序列,而是单调不下降序列,如{2,3,3}是合法的
输入格式
输出格式
样例输入
2
6 3 1 4 5 8 7
6 3 2 1 6 5 4
样例输出
Yes!
No!
数据范围与提示
思路:设f[i][j]为第一个序列以a[i]结尾,第二个序列长度为j且最后一个数为f[i][j]
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int maxn=2000+10,inf=0x3f3f3f3f; 6 int f[maxn][maxn],a[maxn]; 7 void solve(){ 8 memset(f,0x3f,sizeof(f));//初始化 9 int n; 10 scanf("%d",&n); 11 for(int i=1;i<=n;i++) scanf("%d",&a[i]); 12 f[1][1]=a[1]; 13 f[1][0]=0; 14 //注意初始化,f[1][1]据定义为前1个数第一的序列最后一个数为a[1],第二个序列长度为1且最后一个数的最小值为f[1][1],由于两个序列可以互换,所以f[1][1]可确定为a[1] 15 for(int i=1;i<=n;i++){ 16 for(int j=0;j<=min(n/2,i);j++){//f[i+1][...]可由两种状态转移过来 17 if(a[i+1]>=a[i]) f[i+1][j]=min(f[i][j],f[i+1][j]);//此时a[i+1]可直接接在f[i][j]的第一个序列后边 18 if(a[i+1]>=f[i][j]) f[i+1][i-j]=min(a[i],f[i+1][i-j]);//f[i][j]时第一个序列长度为i-j,最后一个数为a[i],第二个序列长的为j, 19 } //最后一个数最小为f[i][j],把a[i+1]归到第二个序列,第二个序列就成了最后一个数为 20 //a[i+1],则第一个序列与第二个互换位置,为f[i+1][i-j],而第二个序列最后一个为a[i] 21 } 22 if(f[n][n/2]!=inf) printf("Yes! "); 23 else printf("No! "); 24 } 25 int main(){ 26 int m; 27 scanf("%d",&m); 28 for(int i=1;i<=m;i++){ 29 solve(); 30 } 31 return 0; 32 }
以上是关于dp(水题大战)的主要内容,如果未能解决你的问题,请参考以下文章