描述
有n個硬幣排成一排,每個硬幣上用一個數字標識了它的價值。每次要你從最左邊或者最右邊拿出一個硬幣。總共拿k次,寫一個算法,使能拿到的硬幣的價值和最大。
關於輸入
輸入包含兩行,第一行爲n, k;
第二行包含n個數字,表示n個硬幣的價值。
1 <= k <= n <= 100000
單個硬幣的價值大於0且不超過10000.
關於輸出
輸出可以拿到的k個硬幣最大的價值和。
例子輸入
6 3
5 4 3 2 1 6
例子輸出
15
由於只能連續地取左邊幾個和右邊幾個,所以答案是對 [0 , k] 之間的 i ,前面 i 個數和後面 k-i 個數的和的最大值。用表示第 i 個數,於是有這個方程:
但是,如果對於每個 i 都算一下兩個求和,肯定會超時(根據許多人的經驗)
這裏我們用前綴和優化一下,省略掉求和的過程(CSDN上可以搜到詳細解說)
用ps[i]表示前i個數的和
所以第i個數到第j個數的和等於ps[j]-ps[i-1]
這樣,上面的式子可以換成:
讓 i 走一遍循環,即可得出結果。
廢話不說,上代碼
C++
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
int ps[100005];
int main(){
int n,k,ma=0;
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++){
scanf("%d",&ps[i]);
ps[i]+=ps[i-1];//求出前綴和
}
for(int i=0;i<=k;i++)
ma=max(ma,ps[i]+ps[n]-ps[n-(k-i)]);
printf("%d",ma);
return 0;
}
C
#include<stdio.h>
#include<string.h>
int ps[100005];
int main(){
int n,k,i,ma=0;
scanf("%d%d",&n,&k);
for(i=1;i<=n;i++){
scanf("%d",&ps[i]);
ps[i]+=ps[i-1];//求出前綴和
}
for(i=0;i<=k;i++)
if(ma<ps[i]+ps[n]-ps[n-(k-i)])
ma=ps[i]+ps[n]-ps[n-(k-i)];
printf("%d",ma);
return 0;
}