如果n是偶数,很显然最少需要最大的两个相邻士兵的要求礼物和.
如果n是奇数,那就要二分答案了,对于p个礼物,第1个人需要r[1]个礼物,记为左边的礼物,剩下的p-r[1]个礼物记为右边礼物,对于2..n 如果是偶数,尽量在左边的礼物里选礼物,如果奇数,尽量在右边的礼物里面选.
#include <iostream>
#include <cstdio>
using namespace std;
const int maxn = 100010;
int r[maxn], right1[maxn], left1[maxn], n;
bool ok(int p){
int x = r[1], y = p - r[1];
left1[1] = x, right1[1] = 0;
for(int i = 2; i <= n; ++i){
if(i % 2 == 1){//奇数位上的人尽量先取右边的
right1[i] = min(y - right1[i - 1], r[i]);
left1[i] = r[i] - right1[i];
}else{
left1[i] = min(x - left1[i - 1], r[i]);
right1[i] = r[i] - left1[i];
}
}
return left1[n] == 0;
}
int main(){
while(scanf("%d", &n) == 1&& n){
for(int i = 1; i <= n; ++i){
scanf("%d", &r[i]);
}
if(n == 1){
printf("%d\n", r[1]);
continue;
}
r[n + 1] = r[1];
int L = 0, R = 0;
for(int i = 1; i <= n; ++i){
L = max(L, r[i] + r[i + 1]);
}
if(n % 2 == 1){
for(int i = 1; i <= n; ++i){
R = max(R, r[i] * 3);
}
while(L < R){
int M = L + (R - L) / 2;
if(ok(M)){
R = M;
}else{
L = M + 1;
}
}
}
printf("%d\n", L);
}
return 0;
}