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