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\n",sum,num);
43 }
44 }
来源:oschina
链接:https://my.oschina.net/u/4392164/blog/3893777