P1108 低价购买 (动态规划)

本文详细介绍了如何解决在股票交易中选择不同方案、价格不同时找到最长不上升子序列的问题。通过动态规划方法,文章提出了一种新的状态转移方程,并详细解释了如何在DP过程中记录方案数。该方法不仅解决了经典最长不上升子序列问题的限制,还考虑了价格多样性的影响。

题目链接

Solution

似乎就是个很简单的最长不上升子序列输出方案.
但是有一个很艹蛋的条件: 不同方案选择价格必须不同.
且其股票价格不保证不相同.

\(f[i]\) 代表以第 \(i\) 天结尾的不上升子序列的长度.

其实我们可以推出一个条件 : 相同的两个股票价格同时出现,后者的方案里面一定包括前者的.
这也是我们按平常做法多出来的方案数.
所以我们可以直接在 DP 的时候记录一个 \(g[i][j]\) 代表在 \(i\) 时由最后一个价值为 \(j\) 的已经累加的次数.
然后每次加上的便是 \(g[v][j]-g[i][j]\). 其中 \(v\) 为可以转移到 \(i\) 最优方案的节点.

Code

#include<bits/stdc++.h>
using namespace std;
const int maxn=5008;
int w[maxn],n;
int f[maxn];
map<int,int>g[maxn];
map<int,int>v;
int ans,ans_num;
int main()
{
    scanf("%d",&n); w[0]=0x3f3f3f3f;
    for(int i=1;i<=n;i++)
    scanf("%d",&w[i]);
    g[0][w[0]]=1; f[0]=0;
    for(int i=1;i<=n;i++)
    {
        for(int j=0;j<i;j++)
        if(w[i]<w[j])
            if(f[j]+1>f[i])
                f[i]=f[j]+1;
        
        for(int j=0;j<i;j++)
        if(w[i]<w[j])
            if(f[j]+1==f[i])
            {
                g[i][w[i]]+=(g[j][w[j]]-g[i][w[j]]);
                g[i][w[j]]=g[j][w[j]];
            }       
    }
    for(int i=1;i<=n;i++)
        if(f[i]>ans)ans=f[i];
    for(int i=1;i<=n;i++)
        if(f[i]==ans)
        {
            ans_num+=g[i][w[i]]-v[w[i]];
            v[w[i]]=g[i][w[i]];
        }
    cout<<ans<<' '<<ans_num;
    return 0;
}

转载于:https://www.cnblogs.com/Kv-Stalin/p/9673062.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值