P1108 低價購買(DP)

題目描述

「低價購買」這條建議是在奶牛股票市場取得成功的一半規則。要想被認爲是偉大的投資者,你必須遵循如下的問題建議:「低價購買;再低價購買」。每次你購買一支股票,你必須用低於你上次購買它的價格購買它。買的次數越多越好!你的目標是在遵循以上建議的前提下,求你最多能購買股票的次數。你將被給出一段時間內一支股票天天的出售價(2162^{16}216範圍內的正整數),你能夠選擇在哪些天購買這支股票。每次購買都必須遵循「低價購買;再低價購買」的原則。寫一個程序計算最大購買次數。ios

這裏是某支股票的價格清單:數組

日期 1,2,3,4,5,6,7,8,9,10,11,12 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8, 9 ,10 ,11, 121,2,3,4,5,6,7,8,9,10,11,12ide

價格68,69,54,64,68,64,70,67,78,62,98,87 68 ,69 ,54, 64,68 ,64 ,70 ,67 ,78 ,62, 98, 8768,69,54,64,68,64,70,67,78,62,98,87spa

最優秀的投資者能夠購買最多444次股票,可行方案中的一種是:blog

日期 2,5,6,10 2 , 5 , 6 ,102,5,6,10隊列

價格 69,68,64,62 69, 68 ,64 ,6269,68,64,62ip

輸入輸出格式

輸入格式:博客

 

第1行: N(1≤N≤5000)N(1 \le N \le 5000)N(1≤N≤5000),股票發行天數string

第2行: NNN個數,是天天的股票價格。it

 

輸出格式:

 

兩個數:
最大購買次數和擁有最大購買次數的方案數(≤231 \le 2^{31}≤231)當二種方案「看起來同樣」時(就是說它們構成的價格隊列同樣的時候),這222種方案被認爲是相同的。

 

輸入輸出樣例

輸入樣例#1: 複製
12
68 69 54 64 68 64 70 67 78 62 98 87
輸出樣例#1: 複製
4 2

題解:

注意這不是LIS,由於它還要求出來方案數,而LIS的DP數組裏面只是求出來了以dp[i]以第i個數結尾的LIS,並且這道題還要求咱們去重<_>

 

所以我參考了一下別人的博客https://wjyyy.blog.luogu.org/solution-p1108

  1. 若是一個數列的第一個數與另外一個數列的第一個數相同,那麼如今能夠判斷它們相等,便可以把其中一個刪掉(在代碼中的處理是t[i]=0t[i]=0t[i]=0)。當不一樣的數接在它的後面時,又能夠將它們判斷爲兩個數列,這是不互相影響的。由於兩個數列均可以由這個相等的數列轉移而來
  2. 若是一個數列的第一個數與另外一個數列的第一個數不一樣,那麼它們不等,且不管後面添加什麼,都不相等,即不刪去,則按照普通的判斷繼續作。

由上面的兩點,咱們已經把重複的刪掉,這樣能夠防止重複計數

tiptiptip:本題若是出如今考試中,請不要冒險定義int,由於maxint是231−12^{31}-1231−1,會爆int,這個題暫不作深究

 

上代碼:

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<iostream>
 4 #include<algorithm>
 5 using namespace std;
 6 const int maxn=1000005;
 7 int v[maxn],dp[maxn],t[maxn];
 8 int main()
 9 {
10     int n,m,maxx=0;
11     scanf("%d",&n);
12     m=n;
13     for(int i=1;i<=n;++i)
14         scanf("%d",&v[m--]);
15     for(int i=1;i<=n;++i)
16     {
17         dp[i]=1;
18         for(int j=1;j<i;++j)
19         {
20             if(v[j]<v[i] && dp[j]+1>dp[i])
21                 dp[i]=dp[j]+1;
22         }
23         maxx=max(maxx,dp[i]);
24 
25         for(int j=1;j<i;++j)
26         {
27             if(dp[j]==dp[i] && v[j]==v[i])
28                 t[j]=0;
29             else if(dp[j]+1==dp[i] && v[j]<v[i])
30                 t[i]+=t[j];
31         }
32         if(!t[i]) t[i]=1;
33     }
34     int sum=0;
35     for(int i=1;i<=n;++i)
36     {
37         if(dp[i]==maxx)
38             sum+=t[i];
39     }
40     printf("%d %d\n",maxx,sum);
41 }
View Code
相關文章
相關標籤/搜索