首页 > 技术文章 > P1108 低价购买 DP

ltdjcoder 2020-09-19 21:13 原文

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;
}

 

   

推荐阅读