低买题解

前言

假期第一篇题解

题目

题目描述
给定一段时间内股票的每日售价(正16位整数)。

你可以选择在任何一天购买股票。

每次你选择购买时,当前的股票价格必须严格低于你之前购买股票时的价格。

编写一个程序,确定你应该在哪些天购进股票,可以使得你能够购买股票的次数最大化。

例如,下面是一个股票价格时间表:

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

输入格式

第1行包含整数 N,表示给出的股票价格的天数。

第2至最后一行,共包含 N 个整数,每行10个,最后一行可能不够10个,表示 N 天的股票价格。

同一行数之间用空格隔开。

输出格式

输出占一行,包含两个整数,分别表示最大买进股票次数以及可以达到最大买进次数的方案数。

如果两种方案的买入日序列不同,但是价格序列相同,则认为这是相同的方案(只计算一次)。

样例

样例1输入

12

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

样例1输出

4 2

样例2输入

5

4 3 2 1 1

样例2输出

4 1

数据范围与提示

1≤N≤5000

------------------------------------------------气愤的分割线-------------------------------------------------------------

第一问,明显LIS,直接摸板,关键在于第二问

第二问
设数组F来表示从1到i的方案总数,F[i]=1

那么如果前一个a[j]+1==a[i],那么可以确定F[i]是按照F[j]得来的,并且这时如果a[j]>a[i],可以再买一张股票,符合要求,那么就把F[j]加到F[i]里

	if(a[j]>a[i]&&dp[i]==dp[j]+1)
	  {
		 		F[i]+=F[j];
		 }

而如果a[j]==a[i]且dp[j]==dp[i],那么F[i]的方案一定在F[j]里,此时直接把F[i]置为0,并不会影响后面的答案(加0没影响噻~)

所以


if(a[i]==a[j]&&dp[i]==dp[j])
	{
		F[i]=0;
	 } 

最后再用一个循环判断如果dp[i]==maxi,则ans+=F[i]

完整代码

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
long long n,a[5010],dp[5010],k[5010],maxi=0,ans=0;
int main()
{
	 memset(a,0,sizeof(a));
	 memset(dp,0,sizeof(dp));
     scanf("%lld",&n);
     if(n==1)
     {
     	for(int i=1;i<2;i++)
     	{
     		scanf("%lld",&a[i]);
		 }
     	printf("1 1");
     	return 0;
	 }//加了个特判骗了9分qwq
	 for(int i=1;i<=n;i++)
	 {
	    scanf("%lld",&a[i]);
     	dp[i]=1;	
		 for(int j=1;j<i;j++)
	 	{
	 		if(a[j]>a[i]&&dp[j]+1>dp[i])
	 		{
	 			dp[i]=dp[j]+1;
	 			maxi=max(maxi,dp[i]);
			 }
		 }
     }
    for(int i=1;i<=n;i++)
      {	
		if(dp[i]==1)
		{
		 	k[i]=1;
			}
		for(int j=1;j<i;j++)
		 {
		 
		 	if(a[j]>a[i]&&dp[i]==dp[j]+1)
		 	{
		 		k[i]+=k[j];
			 }
			 if(a[i]==a[j]&&dp[i]==dp[j])
			 {
			 	k[i]=0;
			 } 
	     }
     }
     for(int i=1;i<=n;i++)
     {
     	if(dp[i]==maxi)
     	{
     		ans+=k[i];
       }
	 }
	 printf("%lld %lld",maxi,ans);
	 return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值