洛谷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;
废话不多说,上代码!
思路:
这题有两种方法,第一种用动态规划,另一种用二分答案,这里介绍的是动态规划方法。
首先这题其实就是最长下降序列+统计方案数
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(); }
相关文章推荐
- 洛谷1108 低价购买
- |洛谷|动态规划|P1108 低价购买
- 洛谷[1108]低价购买 DP
- (洛谷 1108)低价购买
- 洛谷 1108 低价购买
- [洛谷1108]低价购买
- 洛谷P1108 低价购买题解
- 洛谷 P1108 低价购买
- 动态规划入门 洛谷P1108 低价购买
- 洛谷 P1108 低价购买
- 动态规划基础题:低价购买(最长下降子序列)
- 【洛谷P1108】 低价购买[LIS方案数]
- 洛谷 P1108 低价购买
- 洛谷 P1108 低价购买
- 洛谷P1108 低价购买
- 洛谷P1108 低价购买
- 低价购买(动态规划)
- 【洛谷P1108】低价购买【dp练习】
- 洛谷 P1108 低价购买
- 低价购买(动态规划)