<序列DP>codevs 4748 低价购买
来源:互联网 发布:阿里云搭ss 编辑:程序博客网 时间:2024/05/22 01:29
这里是题面
–这是一道计算不重复的最长下降子序列的方案数的题
–首先很容易想到,先计算最长下降子序列,然后遍历一遍f数组,如果f[i]==LDS,ans++
–但这样一定有重复的计算
–去重1:
记g[i]为以第i个数结尾的最长下降子序列的方案数,那么g[i]一定是由点g[j]转移而来,g[j]满足:j < i ,a[j] > a[i],f[j]==f[i]-1。但是,如果在a[i]前有k个数字和a[j]相等,那么只有最后一个和它相等的数(有可能是他自己)转移过来的才是答案,其他的都是重复的计算,所以我们可以用bool数组,倒序循环,如果一个数被纪录过答案,直接跳过,那么最后的答案就是所有f[i]==LDS的g[i]的和
但是用bool数组,数组开不了这么大,codevs又显示我TLE,那就用map吧
–去重2:
但是,如果有这种情况:
a:3 2 2
g:1 1 1
这样,答案就会被记为2,显然答案应该是1
也就是说,我们忽略了a[i]本身和a[j]相等的情况,没有去重
我们可以在a数组末尾添一个极小值,保证不会有前面和他重复的数,那么最后的方案数就是g[n]
记得最长下降子序列的长度要减一
代码:
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<map>using namespace std;const int maxn=5000+10;int n,ans,maxx;int a[maxn],g[maxn],f[maxn];bool vis[maxn*1000];int main(){ scanf("%d",&n); for(int i=1;i<=n;++i) scanf("%d",&a[i]); n++; a[n]=-1e9; for(int i=1;i<=n;++i) f[i]=1; for(int i=1;i<=n;++i) for(int j=i-1;j>=1;--j) if(a[j]>a[i]) f[i]=max(f[i],f[j]+1); for(int i=1;i<=n;++i) maxx=max(maxx,f[i]); for(int i=1;i<=n;++i) { if(f[i]==1) g[i]=1; else { map<int,bool>vis; for(int j=i-1;j>=1;--j) if(a[j]>a[i]&&f[j]==f[i]-1&&!vis[a[j]]) { vis[a[j]]=1; g[i]+=g[j]; } } } printf("%d %d",maxx-1,g[n]); return 0;}
阅读全文
1 0
- <序列DP>codevs 4748 低价购买
- Codevs 4748 低价购买 最长下降子序列方案数
- P1108 低价购买dp
- RPNOJ[456]洛谷[1108]低价购买 DP
- 低价购买 洛谷1108 codevs4748 dp
- 【洛谷P1108】低价购买【dp练习】
- 低价购买
- 低价购买
- 低价购买
- 低价购买
- 低价购买
- 低价购买
- 低价购买
- 低价购买
- 低价购买
- 低价购买
- 低价购买
- rqnoj-低价购买
- JSP中的动作
- Guthcad.CAD.Viewer.v8.0.A.33-REDT\
- C++ 文件和流
- 用递归方法产生格雷码;
- 计算数据库存储空间的jdbc实现
- <序列DP>codevs 4748 低价购买
- pcm基础知识
- ACM第二次STUV
- Linux 目录配置 —— FHS
- 加密解密算法介绍
- LightRNN —— 基于RNN的轻量级语言模型
- Mongodb常见的问题
- Salary Inequity
- YUV基础知识