牛客网 暑期ACM多校训练营(第二场)D.money-贪心 or 动态规划

D.money

贪心,直接贴官方的题解吧。

题目大意

你要按照顺序依次经过n个商店,每到达一个商店你可以购买一件商品,也可以出售你手中的商品。 同一时刻你手上最多拿一件商品。在第i个商店购买和出售的代价都是a[i]。 问你经过完n个商店后的最大收益。 同时,在最大化收益的前提下,求最小的交易次数。 

做法

 DP

f[i][0/1]表示已经访问完了i个商店,你手中是否有商品,此时的最大收益。 g[i][0/1]表示当f[i][j]取最大值时最少的交易次数。

贪心

首先,如果a[i]=a[i+1],则可以删掉第i+1个商店。因为任何在第i+1个商店进行的交易都可以转为在第i个商店 进行,且收益不变。之后,如果a[i]<a[i+1],则离开第i个商店时一定要带上一件商品。如果a[i]>a[i+1],则离开 第i个商店时一定要空着手。这样,第一问的答案就为,第二问的答案就为长度>1的 极大递增连续段的数量。

反正贪心就可以,按队友思路写的代码:

 1 //D-贪心
 2 #include<iostream>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<cmath>
 6 #include<algorithm>
 7 #include<queue>
 8 #include<stack>
 9 #include<map>
10 #include<cctype>
11 #include<cstdlib>
12 
13 typedef long long ll;
14 const int maxn=1e5+10;
15 const int inf=0x3f3f3f3f;
16 const int mod=1e9+7;
17 const double eps=1e-5;
18 ll a[maxn];
19 
20 int main()
21 {
22     int t;
23     scanf("%d",&t);
24     while(t--){
25         int n;
26         scanf("%d",&n);
27         for(int i=0;i<n;i++)
28             scanf("%lld",&a[i]);
29         a[n]=-1;
30         ll sum=0,minn=a[0],maxx=a[0];
31         int num=0,i=0;
32         while(1){
33             i++;
34             if(i>n)break;
35             if(a[i]<maxx){
36                 if(maxx!=minn) num+=2;
37                 sum+=maxx-minn;
38                 maxx=minn=a[i];
39             }
40             maxx=std::max(maxx,a[i]);
41         }
42         printf("%lld %d
",sum,num);
43     }
44 }
原文地址:https://www.cnblogs.com/ZERO-/p/9359346.html