ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

P1969积木大赛

2019-12-05 18:03:42  阅读:258  来源: 互联网

标签:bf 积木 int 大赛 最小值 num P1969 ans 第二座


这是一到洛谷的题目:https://www.luogu.com.cn/problem/P1969

在搭建开始之前,没有任何积木(可以看成nnn块高度为000的积木)。接下来每次操作,小朋友们可以选择一段连续区间[l,r][l, r][l,r],然后将第第L L L块到第 RRR 块之间(含第L LL 块和第 RR R块)所有积木的高度分别增加111。

小M M M是个聪明的小朋友,她很快想出了建造大厦的最佳策略,使得建造所需的操作次数最少。但她不是一个勤于动手的孩子,所以想请你帮忙实现这个策略,并求出最少的操作次数。

一看到这道题,我是这样想的,找到一段中的最小值,然后每个数都减去最小值,ans加上最小值,一开始没发现这是一种递归思想(我太菜了),一段一段的。后来看了别人家的题解,才恍然大悟原来可以这样啊。那到底是怎么样的呢?首先这是一种递归的思想,我们一开始可以先从1到n开始,先是找到它们之中的最小值,也就是将它们全部历经一边找最小值,然后将在这一段上的数减去这个最小值min,在这之后就可以进行下一步的递归了,将1~n划分为两段,一是1~min-1,二是min+1~n,因为min这个数已经被减到0,所以可以不管它了,就这样递归下去。它的跳出条件就是before  >=  end 这样就说明中间的已经处理完了,还剩下了一个所以ans += num[before] ,还需要注意的是,因为我们找的是最小值,然后再减去最小值,所以无法避免的是,在最边上会有0的情况,所以我们可以再加上一个条件来判断;

看代码  这里的minn和index注意用局部变量,要不然容易错。

 1 #include <cstdio>
 2 #include <iostream>
 3 
 4 using namespace std;
 5 const int inf = 0x3f3f3f3f;
 6 const int ma = 1e5 + 10;
 7 int ans,n,num[ma];
 8 
 9 void slove(int bf,int en)
10 {
11     if(bf >= en)
12     {
13         ans += num[bf];
14         return ;
15     }
16     if(num[bf] == 0)
17     {
18         slove(bf+1,en);return ;
19     }
20     if(num[en] == 0)
21     {
22         slove(bf,en-1);return ;
23     }
24     int minn = num[bf];
25     int index = bf;
26     for(int i = bf;i <= en;i++)
27         if(num[i] < minn)
28             minn = num[i],index = i;
29     for(int i = bf;i <= en;i++)
30         num[i] -= minn;
31     ans += minn;
32     slove(bf,index-1);
33     slove(index+1,en);
34 }
35 
36 int main()
37 {
38     scanf("%d",&n);
39     for(int i = 1;i <= n;i++)
40         scanf("%d",&num[i]);
41     int minn = inf;
42     int index;
43     for(int i = 1;i <= n;i++)
44     {
45         if(minn > num[i])
46             minn = num[i],index = i;
47     }
48     ans += minn;
49     for(int i = 1;i <= n;i++)
50         num[i] -= minn;
51     slove(1,index-1);
52     slove(index+1,n);
53     printf("%d",ans);
54     return 0;
55 }
View Code

 

如果真的理解了这道题目,你就会发现根本都不用这么麻烦。我们在这里建大厦,那么我们可以从第一个开始建,所以ans += num[1] ,现在已经建完了第一座大赛,下一个是第二座大厦了,然后我们就可以比较一下,是第一座高还是第二座高,如果是第二座大厦高的话,我们只需要加上(num[2] - num[1] )就行了,因为再第一座再建造的是第二座大厦也可以一起建造,所以只剩下高的部分没建完;如果第二座大厦矮的话,在第一座还没建完的时候,第二座就已经竣工了。然后就是第三座和第二座相比较···第n-1和第n座相比较。然后答案就出来了。这样建造的即使最少的操作数。因为这样保证了连续性。

看代码:

 1 #include <cstdio>
 2 #include <iostream>
 3 
 4 using namespace std;
 5 const int ma = 1e5 + 10;
 6 int n,num[ma];
 7 
 8 int main()
 9 {
10     scanf("%d",&n);
11     for(int i = 1;i <= n;i++)
12         scanf("%d",&num[i]);
13     int ans = num[1];
14     for(int i = 1;i < n;i++)
15     {
16         if(num[i+1] > num[i])
17             ans += num[i+1] - num[i];
18     }
19     printf("%d",ans);
20     return 0;
21 }
View Code

 

标签:bf,积木,int,大赛,最小值,num,P1969,ans,第二座
来源: https://www.cnblogs.com/d1s2y3/p/11990853.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有