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!\n");
23     else printf("No!\n");
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 }
View Code

猜你喜欢

转载自www.cnblogs.com/HZOIDJ123/p/13368796.html