标签:动态规划
| Time Limit: 1000MS | Memory Limit: 30000K | |
Description
"Buy low; buy lower"
Day 1 2 3 4 5 6 7 8 9 10 11 12 Price 68 69 54 64 68 64 70 67 78 62 98 87
Day 2 5 6 10 Price 69 68 64 62
Input
Output
Sample Input
12 68 69 54 64 68 64 70 67 78 62 98 87
Sample Output
4 2
题意:给出n个数,求最长单调递减子序列的长度L,并求出有多少个序列的长度为L。
注意:5 3 1, 5 3 1算一种方案。
分析:因为n不超过5000,所以O(n^2)复杂度可以接受。那么我们就可以按照平时求最长单调递减子序列的方法,在求的时候加上一个辅助数组cnt[i]记录从开始到第i个位置,单调递减子序列为dp[i]时的方案数。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1e4 + 10;
int a[N], dp[N], cnt[N];
int main() {
int n;
while(~scanf("%d", &n)) {
for(int i = 0; i < n; i++) {
scanf("%d", &a[i]);
dp[i] = 1;
cnt[i] = 1;
}
for(int i = 1; i < n; i++) {
for(int j = i - 1; j >= 0; j--) {
if(a[i] < a[j]) {
if(dp[i] < dp[j] + 1) { // 第一次找到能使长度变长的元素
dp[i] = dp[j] + 1;
cnt[i] = cnt[j];
}
else if(dp[i] == dp[j] + 1) // 之前已经找到了一个使得dp[i] = dp[j] +1的元素,现在又找到一个
cnt[i] += cnt[j];
}
else {
if(a[i] == a[j]) {
if(dp[i] == 1) //用第i个位置上的数字替换第j个位置上的数字,形成的序列完全相同
cnt[i] = 0;
break;
}
}
}
}
int max_len = 0, ans_cnt = 0;
for(int i = 0; i < n; i++)
max_len = max(max_len, dp[i]);
for(int i = 0; i < n; i++)
if(dp[i] == max_len)
ans_cnt += cnt[i];
printf("%d %d\n", max_len, ans_cnt);
}
return 0;
}POJ 1552 BUY LOW, BUY LOWER(最长单调递减子序列求方案数)
标签:动态规划
原文地址:http://blog.csdn.net/lyhvoyage/article/details/45392257