POJ 1952 BUY LOW, BUY LOWER DP 最长下降序列求个数
注意:重复的只算一次
如何去掉一些重复的是本题的关键
我的去重思路:
7
5 3 7 6 3 2 1
6
5 3 7 3 1
5
5 3 2 1 3
第一组在推到 数字 2 的时候有 3会出现重复, 显然前面一个3是可有可无的。
第二组也一样,前面一个3是可有可无的。
1.如果最长下降序列中有后面一个3, 如第一二组数据,那么前面一个3是无用的,在推好后面一个3之后把之前的所用重复的计数数组清零
2.如果最长下降序列中只有前面一个3,如第三组数据, 做情况1的操作也是不会影响结果的,因为第三组的前面一个3的状态已经推到2后才被清零的。
View Code
#include<stdio.h> #include<string.h> bool vis[5003]; int a[5003], dp[5003], cnt[5003]; int main() { int i, j, k, max, n; while( ~scanf("%d", &n)) { int id = 0; for(i = 1; i <= n; i++) scanf("%d", &a[i]); memset(dp, 0, sizeof(dp)); memset(cnt, 0, sizeof(cnt)); int max = 0; for(i = 1; i <= n; i++) { //求长度 k = 0; for(j = 1; j < i; j++) if(a[i] < a[j] && dp[k] < dp[j]) k = j; dp[i] = dp[k] + 1; if(max < dp[i]) max = dp[i]; //求个数 if(dp[i] == 1) cnt[i] = 1; else { for(j = 1; j < i; j++) if(dp[j] + 1== dp[i] && a[i] < a[j]) cnt[i] += cnt[j]; } for(j = 1; j < i; j++) if(a[i] == a[j]) cnt[j] = 0; } int ans = 0; for(i = 1; i <= n; i++) if(max == dp[i]) ans += cnt[i]; printf("%d %d\n", max, ans); } return 0; }


浙公网安备 33010602011771号