您的位置:首页 > 其它

洛谷1108低价购买(动态规划练习题)

2017-12-20 17:49 141 查看
题目:https://www.luogu.org/problemnew/show/1108



思路:

这题有两种方法,第一种用动态规划,另一种用二分答案,这里介绍的是动态规划方法。

首先这题其实就是最长下降序列+统计方案数

a[i]表示第i种股票

b[i]表示前i个数的最长下降序列长度

f[i]表示到b[i]的方案个数

如果(b[j]+1=b[i])and(a[i]<a[j]) 也就是满足不下降且可以到达这里,那么f[i]=f[i]+f[j];但是我们会发现,如果前面有两种价格相等的股票,且到这两种股票的最长下降序列长度相等,也就是方案重复,那么此时的f[j]=0;

动态转移方程

f[i]+=(a[i]<a[j]&&b[j]+1==b[i])?f[j]:(a[i]==a[j]&&b[i]==b[j])?-f[i]:0;

废话不多说,上代码!

#include<cstdio>
#include<cstring>
#define k freopen
#define r(i,a,b) for (int i=a;i<=b;i++)//循环
using namespace std;int n,ans1,ans2;//ans1是最长下降序列的长度,ans2是方案数
long long a[5001],b[5001],f[5001];//前面已经解释过了
int max(int x,int y)//推荐还是自己定义比较好
{
return x>y?x:y;
}
void LRZ()//输入
{
ans1=1;
scanf("%d",&n);
r(i,1,n)
scanf("%d",&a[i]),b[i]=1;//最长下降
}
void LDS()//b[i]的值,用于理解
{
r(i,1,n)
printf("%d ",b[i]);
}
void dp()
{
r(i,1,n)
{
r(j,1,i-1)
if (a[j]>a[i]&&b[j]+1>b[i])//先把到i的最长下降序列求下来
{
b[i]=b[j]+1;
ans1=max(ans1,b[i]);//取下最大值
}
if (b[i]==1) f[i]=1;//如果它的长度是1,那么它的方案数也是一,因为没有长度为0的序列
r(j,1,i-1)//从1到i-1
f[i]+=(a[i]<a[j]&&b[j]+1==b[i])?f[j]:(a[i]==a[j]&&b[i]==b[j])?-f[i]:0;//动态转移
}
}
void print()
{
printf("%d ",ans1);
r(i,1,n)
if (b[i]==ans1)
ans2+=f[i];//把所有的方案加在一起
printf("%d",ans2);//输出
}
int main()
{
LRZ();
dp();
print();
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: