P1108 低价购买 DP

P1108 低价购买 DP 

题意:

  给定一个序列, 求最长下降子序列,及不重复的方案数。

  洛谷链接

题解:

  最长下降子序列可以用 O(n^2) 的简单dp来求。  

  不难发现: 在一个元素互不相同的序列中,不会出现重复方案,因此可以通过dp累计答案(详见代码)。然后考虑去重,发现以x结尾的最长序列, 位置靠后的x的方案会包括位置靠前的x的方案。 因此可以删除最后一个x之前的x,dp后剩下的序列是互异的,因此答案不重复。

 

代码:

  蒟丑

复制代码
#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm> 
#define inf 0x3f3f3f3f
using namespace std;

struct p{
    int v=inf, l=0, a=0;
}f[5005], lp;

int n, ans=0, ans1=0;
bool cmp(const p& a, const p& b){return a.l>b.l;}

int main(){
    scanf("%d", &n);f[0].a=1;
    for(int i=1; i<=n; i++) scanf("%d", &f[i].v);
    
    for(int i=1; i<=n; i++){
        for(int j=0; j<i; j++){
            
            if(f[j].v == f[i].v) f[j].v = inf, f[j].l = -inf;
            else if(f[j].v < f[i].v || f[j].l < f[i].l-1) continue;
            else if(f[j].l == f[i].l-1) f[i].a += f[j].a;
            else f[i].l = f[j].l + 1, f[i].a = f[j].a; 
            
        } 
    }
    
    sort(f+1, f+n+1, cmp);
    int end = 2;while(f[end].l == f[end-1].l) end++;

    for(int i=1; i<end; i++) ans=f[i].l, ans1 += f[i].a;
    cout << ans << ' ' << ans1;
    
    return 0;
}
复制代码

 

   

posted @   ltdJcoder  阅读(141)  评论(0)    收藏  举报
编辑推荐:
· 行业思考:不是前端不行,是只会前端不行
· C#高级GDI+实战:从零开发一个流程图
· 2025年:是时候重新认识System.Text.Json了
· 源码浅析:SpringBoot main方法结束为什么程序不停止
· C#性能优化:为何 x * Math.Sqrt(x) 远胜 Math.Pow(x, 1.5)
阅读排行:
· 一款实用的 Visual Studio 发布部署插件,助力提高部署效率!
· 独立开发在线客服系统,我是如何与杀毒软件误报斗智斗勇的
· 换成.NET 9,你的LINQ代码还能快上7倍
· AI 时代,为什么我们还有必要写博客?
· where 1 = 1的作用?会影响性能吗?count(*) 和 count(1)哪个快?
点击右上角即可分享
微信分享提示