题解——P1108低价购买(DP)

第一问是最长下降子序列,n很小,n^2可过,注意最长下降子序列的枚举顺序即可

for(int i=1;i<=n;i++)//不要写错
    for(int j=1;j<i;j++)//不要打成<=
        if(a[i]<a[j]&&b[i]<b[j]+1)
            b[i]=b[j]+1;

第二问统计方案数

我们设cnt[i]表示以i结尾的最长下降子序列的长度

然后转移方案数

如果a[i]<a[j]&&b[i]==b[j]+1

就可以把原序列拼接上去

如果相等,则前面已经包含此情况,b[j]=0

over

#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
int a[5050],b[5050],c[5050],n,ans=1,cnt[5050],ansc=0;
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]),b[i]=1,c[i]=i;
    for(int i=1;i<=n;i++){
        for(int j=1;j<i;j++)
            if(a[i]<a[j]&&b[j]+1>b[i]){
                b[i]=b[j]+1;
                c[i]=j;
                ans=max(ans,b[i]);
            }
        if(!b[i])
            b[i]=1;
    }
 //   for(int i=1;i<=n;i++)
 //       printf("i=%d a=%d b=%d\n",i,a[i],b[i]);
    for(int i=1;i<=n;i++){
        for(int j=1;j<i;j++){
            if(a[i]<a[j]&&b[i]==b[j]+1)
                cnt[i]+=cnt[j];
            else if(a[j]==a[i]&&b[j]==b[i]){
                cnt[j]=0;
                }
             }
            if(!cnt[i])
                cnt[i]=1;
    }
    for(int i=1;i<=n;i++)
        if(b[i]==ans){
            ansc+=cnt[i];
        }  
    printf("%d %d\n",ans,ansc);
    return 0;
}

 

posted @ 2018-08-20 12:54  dreagonm  阅读(193)  评论(0编辑  收藏  举报