UVALive 3177 长城守卫

https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1178

http://7xjob4.com1.z0.glb.clouddn.com/8e1ee1ef5ea10e46ebda75b88b058f47

题意:n个人围圈,每人有不同或相同数量礼物,相邻礼物不能一样,求最少总礼物数。

思路: n是偶数:为相邻两人礼物数和的最大值;n是奇数:二分法选礼物数量,看是否可行,设第一个人礼物为前几种,编号为偶数的人尽量在前面取,奇数的人尽量在后面取,最后查看最后一人的礼物是否和第一个人的冲突。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 int n;
 5 int r[100005],Left[100005],Right[100005];
 6 
 7 int check(int p)
 8 {
 9     int i,j;
10     int x=r[1],y=p-r[1];
11     Left[1]=x,Right[1]=0;
12     for(i=2;i<=n;i++)
13     {
14         if(i%2==0)
15         {
16             Left[i]=min(x-Left[i-1],r[i]);
17             Right[i]=r[i]-Left[i];
18         }
19         else
20         {
21             Right[i]=min(y-Right[i-1],r[i]);
22             Left[i]=r[i]-Right[i];
23         }
24     }
25     if(Left[n]==0)
26         return 1;
27     return 0;
28 }
29 
30 int main()
31 {
32     int i,j;
33     while(scanf("%d",&n)!=EOF && n!=0)
34     {
35         for(i=1;i<=n;i++)
36         {
37             scanf("%d",&r[i]);
38         }
39         if(n==1)
40         {
41             printf("%d
",r[1]);
42             continue;
43         }
44 
45         int L=0,R=0;r[n+1]=r[1];
46         for(i=1;i<=n;i++)   L=max(L,r[i]+r[i+1]);
47         if(n%2==1)
48         {
49             for(i=1;i<=n;i++)   R=max(R,r[i]*3);
50             while(L<R)
51             {
52                 int mid=(L+R)/2;
53                 if(check(mid))
54                 {
55                     R=mid;
56                 }
57                 else
58                 {
59                     L=mid+1;
60                 }
61             }
62         }
63         printf("%d
",L);
64     }
65     return 0;
66 }
View Code
原文地址:https://www.cnblogs.com/cyd308/p/5644917.html