问题 F: 积木大赛(模拟)
時間限制: 1 Sec 內(nèi)存限制: 128 MB
[提交][狀態(tài)][討論版]
題目描述
春春幼兒園舉辦了一年一度的“積木大賽”。今年比賽的內(nèi)容是搭建一座寬度為n的大廈,大廈可以看成由n塊寬度為1的積木組成,第i塊積木的最終高度需要是hi。
在搭建開始之前,沒有任何積木(可以看成n塊高度為0的積木)。接下來每次操作,小朋友們可以選擇一段連續(xù)區(qū)間[L, R],然后將第L塊到第R塊之間(含第L塊和第R塊)所有積木的高度分別增加1。
小M是個聰明的小朋友,她很快想出了建造大廈的最佳策略,使得建造所需的操作次數(shù)最少。但她不是一個勤于動手的孩子,所以想請你幫忙實現(xiàn)這個策略,并求出最少的操作次數(shù)。
輸入
每組輸入數(shù)據(jù)包含兩行,第一行包含一個整數(shù)n,表示大廈的寬度。
第二行包含n個整數(shù),第i個整數(shù)為hi。
數(shù)據(jù)規(guī)模:
其中一種可行的最佳方案,依次選擇 [1, 5] [1, 3] [2, 3] [3, 3] [5, 5]
對于30%的數(shù)據(jù),有1≤n≤10;
對于70%的數(shù)據(jù),有1≤n≤1000;
對于100%的數(shù)據(jù),有1≤n≤100000,0≤hi≤10000。
輸出
每組輸出僅一行,即建造所需的最少操作數(shù)。
下面是對樣例數(shù)據(jù)的解釋:
其中一種可行的最佳方案,依次選擇
[1, 5] [1, 3] [2, 3] [3, 3] [5, 5]樣例輸入
5 2 3 4 1 2樣例輸出
5提示
一.樸素解法:
ans = 0;
如果開始只有1堆積木,比如是2
那么 ans += 2 - 0;
有兩堆,2,3
ans += 2-0+3-2;
如果有三堆,2,3,2
ans += 2-0+3-2
四堆:2,3,2,3
ans += 2-0+3-2+3-2
.。。
所以每一堆的只與它前一堆有關,且只有大于前一堆時才需要更新答案,且是加兩者之差
二.遞歸解法:
給的序列還原成全部是0的序列:
每次在序列中找最小,根據(jù)最小的位置可以將原序列劃分為兩個子序列,然后子序列繼續(xù)找最小,繼續(xù)劃分,每次找到最小,將找最小序列全部減去這個最小值(已經(jīng)為0的不再減)
AC_code:
樸素解法:
#include <stdio.h> using namespace std; typedef long long LL; int main() {int n;scanf("%d",&n);int tmp = 0,sum = 0;int x;for(int i = 0; i < n; i++){scanf("%d",&x);if(x > tmp) sum += x-tmp;tmp = x;}printf("%d\n",sum);return 0; }遞歸解法:
#include <bits/stdc++.h> using namespace std; const int MAXN = 1e5+5; int a[MAXN]; int ans; void solve(int l,int r) {if(l > r) return;int minx = 1e5,pos;for(int i = l; i <= r; i++){if(a[i] < minx){minx = a[i];pos = i;}}for(int i = l; i <= r; i++){if(a[i])a[i] -= minx;}ans += minx;solve(l,pos-1);solve(pos+1,r); } int main() {int n;scanf("%d",&n);for(int i = 1; i <= n; i++){scanf("%d",&a[i]);}ans = 0;solve(1,n);printf("%d\n",ans);return 0; }總結(jié)
以上是生活随笔為你收集整理的问题 F: 积木大赛(模拟)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: P1038 神经网络(拓扑排序)
- 下一篇: 2019年湘潭大学程序设计竞赛(重现赛)