P1108 低价购买 dp

Posted bxd123

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P1108 低价购买 dp相关的知识,希望对你有一定的参考价值。

  

题目描述

“低价购买”这条建议是在奶牛股票市场取得成功的一半规则。要想被认为是伟大的投资者,你必须遵循以下的问题建议:“低价购买;再低价购买”。每次你购买一支股票,你必须用低于你上次购买它的价格购买它。买的次数越多越好!你的目标是在遵循以上建议的前提下,求你最多能购买股票的次数。你将被给出一段时间内一支股票每天的出售价(2^{16}216范围内的正整数),你可以选择在哪些天购买这支股票。每次购买都必须遵循“低价购买;再低价购买”的原则。写一个程序计算最大购买次数。

这里是某支股票的价格清单:

日期 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8, 9 ,10 ,11, 121,2,3,4,5,6,7,8,9,10,11,12

价格68 ,69 ,54, 64,68 ,64 ,70 ,67 ,78 ,62, 98, 8768,69,54,64,68,64,70,67,78,62,98,87

最优秀的投资者可以购买最多44次股票,可行方案中的一种是:

日期 2 , 5 , 6 ,102,5,6,10

价格 69, 68 ,64 ,6269,68,64,62

输入输出格式

输入格式:

 

第1行: N(1 \le N \le 5000)N(1N5000),股票发行天数

第2行: NN个数,是每天的股票价格。

 

输出格式:

 

两个数:
最大购买次数和拥有最大购买次数的方案数(\le 2^{31}231)当二种方案“看起来一样”时(就是说它们构成的价格队列一样的时候),这22种方案被认为是相同的。

 

输入输出样例

输入样例#1: 复制
12
68 69 54 64 68 64 70 67 78 62 98 87
输出样例#1: 复制
4 2

第一问是最长下降子序列的长度 第二问是最长长度的序列数

先过一遍n2 dp 然后在所得dp上进行一次dp求数量

注意是将f[i]=0
技术图片
#include<bits/stdc++.h>
using namespace std;
//input by bxd
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i>=(b);--i)
#define RI(n) scanf("%d",&(n))
#define RII(n,m) scanf("%d%d",&n,&m)
#define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define RS(s) scanf("%s",s);
#define ll long long
#define pb push_back
#define REP(i,N)  for(int i=0;i<(N);i++)
#define CLR(A,v)  memset(A,v,sizeof A)
//////////////////////////////////
#define inf 0x3f3f3f3f
const int N=100000+5;
int dp[N];
int f[N];
int a[N];
int main()
{
    int n;RI(n);
    rep(i,1,n)
    RI(a[i]);

    int maxx=0;
    rep(i,1,n)
    {
        dp[i]=1;
        rep(j,1,i-1)
        if(a[i]<a[j])
            dp[i]=max(dp[i],dp[j]+1);

        maxx=max(maxx,dp[i]);
    }
    int cnt=0;
    rep(i,1,n)
    {
        if(dp[i]==1)f[i]=1;
        rep(j,1,i-1)
        {
            if(dp[j]+1==dp[i]&&a[j]>a[i])
            f[i]+=f[j];
            else if(dp[i]==dp[j]&&a[i]==a[j])
            f[i]=0;
        }
        
        if(dp[i]==maxx)cnt+=f[i];
    }
    cout<<maxx<<" "<<cnt;

    return 0;
}
View Code

 


该方法给人觉得更好理解

技术图片
#include<bits/stdc++.h>
using namespace std;
//input by bxd
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i>=(b);--i)
#define RI(n) scanf("%d",&(n))
#define RII(n,m) scanf("%d%d",&n,&m)
#define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define RS(s) scanf("%s",s);
#define ll long long
#define pb push_back
#define REP(i,N)  for(int i=0;i<(N);i++)
#define CLR(A,v)  memset(A,v,sizeof A)
//////////////////////////////////
#define inf 0x3f3f3f3f
const int N=100000+5;
int dp[N];
int f[N];
int a[N];
int main()
{
    int n;RI(n);
    rep(i,1,n)
    RI(a[i]);

    int maxx=0;
    rep(i,1,n)
    {
        dp[i]=1;
        rep(j,1,i-1)
        if(a[i]<a[j])
            dp[i]=max(dp[i],dp[j]+1);

        maxx=max(maxx,dp[i]);

        rep(j,1,i-1)
        {
            if(dp[j]+1==dp[i]&&a[j]>a[i])
            f[i]+=f[j];
            else if(dp[i]==dp[j]&&a[i]==a[j])
            f[j]=0;
        }
        if(!f[i])
        f[i]=1;
    }
    int cnt=0;
    rep(i,1,n)
    if(dp[i]==maxx)
        cnt+=f[i];
    cout<<maxx<<" "<<cnt;


    return 0;
}
View Code

 









以上是关于P1108 低价购买 dp的主要内容,如果未能解决你的问题,请参考以下文章

洛谷P1108 低价购买[DP | LIS方案数]

Luogu P1108 低价购买 DP

题解 P1108 低价购买

P1108 低价购买

入门动态规划 洛谷P1108 低价购买

P1108 低价购买