POJ 1952 BUY LOW, BUY LOWER

链接:http://poj.org/problem?id=1952


BUY LOW, BUY LOWER

Time Limit: 1000MS Memory Limit: 30000K
Total Submissions: 9120 Accepted: 3175

Description


The advice to "buy low" is half the formula to success in the bovine stock market.To be considered a great investor you must also follow this problems' advice:
"Buy low; buy lower"

Each time you buy a stock, you must purchase it at a lower price than the previous time you bought it. The more times you buy at a lower price than before, the better! Your goal is to see how many times you can continue purchasing at ever lower prices.

You will be given the daily selling prices of a stock (positive 16-bit integers) over a period of time. You can choose to buy stock on any of the days. Each time you choose to buy, the price must be strictly lower than the previous time you bought stock. Write a program which identifies which days you should buy stock in order to maximize the number of times you buy.

Here is a list of stock prices:
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


The best investor (by this problem, anyway) can buy at most four times if each purchase is lower then the previous purchase. One four day sequence (there might be others) of acceptable buys is:
Day 2 5 6 10

Price 69 68 64 62

Input


* Line 1: N (1 <= N <= 5000), the number of days for which stock prices are given

* Lines 2..etc: A series of N space-separated integers, ten per line except the final line which might have fewer integers.

Output


Two integers on a single line:
* The length of the longest sequence of decreasing prices
* The number of sequences that have this length (guaranteed to fit in 31 bits)

In counting the number of solutions, two potential solutions are considered the same (and would only count as one solution) if they repeat the same string of decreasing prices, that is, if they "look the same" when the successive prices are compared. Thus, two different sequence of "buy" days could produce the same string of decreasing prices and be counted as only a single solution.

Sample Input

12
68 69 54 64 68 64 70 67 78 62
98 87

Sample Output

4 2

Source

USACO 2002 February


大意——买股票有一个原则:买低价格的,再买更低价格的。现在给你一个数n,表示买股票的天数,再给你每天股票的价格,问:从这些天中选取一些天,使得股票价格严格递减,求选取的天数中满足要求的最大天数,以及最大天数的不同选取有多少种(即序列不相同的而天数相同的种数)。


思路——求最大天数与LIS问题相似,关键是求最大天数的种类。不难发现,如果在后面找到与前面满足条件的那个数,那么在这里的次数应该与前面的相等;如果在此之前找到与现在同样大的天数,那么在这里的次数要加上前面的次数。一旦在后面找到与前面某个数相等并且其最大天数为1时,那么将在这里的次数置为0,以便去掉重复的序列。


复杂度分析——时间复杂度:O(n^2),空间复杂度:O(n)


附上AC代码:


#include <iostream>
#include <cstdio>
#include <string>
#include <cmath>
#include <iomanip>
#include <ctime>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
#include <set>
#include <map>
using namespace std;
typedef unsigned int UI;
typedef long long LL;
typedef unsigned long long ULL;
typedef long double LD;
const double pi = acos(-1.0);
const double e = exp(1.0);
const double eps = 1e-8;
const int maxn = 5005;
int price[maxn], dp[maxn], times[maxn];
// 分别记录股票i的价格,买股票i时的子序列长度以及此长度次数

int main()
{
	ios::sync_with_stdio(false);
	int n;
	while (~scanf("%d", &n))
	{
		for (int i=0; i<n; i++)
		{
			scanf("%d", &price[i]);
			dp[i] = 1;
			times[i] = 1;
		}
		for (int i=1; i<n; i++)
		{
			for (int j=i-1; j>=0; j--)
			{
				if (price[i] < price[j])
				{
					if (dp[i] < dp[j]+1)
					{ // 找到满足条件(长度变化)的数,次数等于前面的次数
						dp[i] = dp[j]+1;
						times[i] = times[j];
					}
					else if (dp[i] == dp[j]+1) // 在此之前找到了一个数满足此
											   // 条件,现在又找到一个,那么
											   // 次数要加上前面的
						times[i] += times[j];
				}
				else if (price[i] == price[j])
				{
					if (dp[i] == 1) // 遇到相同数字,形成序列完全相同
						times[i] = 0;
					break;
				}
			}
		}
		int max_len = 0;
		int ans_times = 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_times += times[i];
		printf("%d %d\n", max_len, ans_times);
	}
	return 0;
}


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值