您的位置:首页 > 其它

ACM: uva 1335 - Beijing Guards

2016-05-19 23:28 411 查看

Beijing Guards

Beijing was once surrounded by four rings of city walls: the
Forbidden City Wall, the Imperial City Wall, the Inner City Wall,
and finally the Outer City Wall. Most of these walls were
demolished in the 50s and 60s to make way for roads. The walls were
protected by guard towers, and there was a guard living in each
tower. The wall can be considered to be a large ring, where every
guard tower has exaetly two neighbors.

The guard had to keep an eye on his section of the wall all day,
so he had to stay in the tower. This is a very boring job, thus it
is important to keep the guards motivated. The best way to motivate
a guard is to give him lots of awards. There are several different
types of awards that can be given: the Distinguished Service Award,
the Nicest Uniform Award, the Master Guard Award, the Superior
Eyesight Award, etc. The Central Department of City Guards
determined how many awards have to be given to each of the guards.
An award can be given to more than one guard. However, you have to
pay attention to one thing: you should not give the same award to
two neighbors, since a guard cannot be proud of his award if his
neighbor already has this award. The task is to write a program
that determines how many different types of awards are required to
keep all the guards motivated.

Input 

The input contains several blocks of test eases. Each case
begins with a line containing a single
integer l n 100000, the number of
guard towers. The
next n lines correspond to
the n guards: each line
contains an integer, the number of awards the guard requires. Each
guard requires at least 1, and at most l00000 awards.
Guard i and i +
1 are neighbors, they cannot receive the same
award. The first guard and the last guard are also neighbors.

The input is terminated by a block
with n = 0.

Output 

For each test case, you have to output a line containing a
single integer, the minimum
number x of award types
that allows us to motivate the guards. That is, if we
have x types of awards,
then we can give as many awards to each guard as he requires, and
we can do it in such a way that the same type of award is not given
to neighboring guards. A guard can receive only one award from each
type.

Sample
Input 

3

4

2

2

5

2

2

2

2

2

5

1

1

1

1

1

0

Sample
Output 

8

5

3

 

 题意: 有n个人, 每人都需要ri种礼物, 但是相邻的人得礼物是不可以相同的,
现在要你求出最少的礼物数

      
满足全部人得需求, 每种礼物的数量是无限的.

 

解题思路:

      
1. 当n为偶数时, 答案是相邻两人之间的的r值最大和, 即p = max{ ri + ri+1 }.

      
2. 当n为偶数时, 采用二分求解, 假设p种礼物是否满足分配:

      
假设: 第一个人得到礼物1~r1, 分配的策略可以是: 偶数编号的人尽量往前取, 奇数的人尽量往

            
后取. 这样需要第n个人在不冲突的条件下, 尽量可能的往后取rn样礼物. 最后判断编号1

            
和编号n的人是否冲突即可.

            
例: p = 8, r = {2,2,5,2,5}

             第一人:{1,2},
第二人:{3,4}, 第三人:{8,7,6,5,2}, 第四人:{1,3}, 第五人:{8,7,6,5,4}

 

代码:

#include <cstdio>

#include <iostream>

#include <cstring>

using namespace std;

#define MAX 100010

int n;

int r[MAX], leftside[MAX], rightside[MAX];

inline int max(int a, int b)

{

 return a > b ? a : b;

}

inline int min(int a, int b)

{

 return a < b ? a : b;

}

bool judge(int p)

{

 int x = r[1], y = p-r[1];

 leftside[1] = x, rightside[1] = 0;

 for(int i = 2; i <= n; ++i)

 {

  if(i % 2 == 1)

  {

   rightside[i]
= min(y-rightside[i-1], r[i]);

   leftside[i] =
r[i] - rightside[i];

  }

  else

  {

   leftside[i] =
min(x-leftside[i-1], r[i]);

   rightside[i]
= r[i]-leftside[i];

  }

 }

 return leftside
== 0;

}

int main()

{

 int i;

// freopen("input.txt", "r", stdin);

 while(scanf("%d", &n) !=
EOF)

 {

  if(n == 0) break;

  for(i = 1; i <=
n; ++i)

   scanf("%d",
&r[i]);

  r[n+1] = r[1];

  int L = 0, R = 0;

  for(i = 1; i <=
n; ++i)

   L = max(L,
r[i]+r[i+1]);

  if(n % 2 == 1)

  {

   for(i = 1; i
<= n; ++i)

    R
= max(R, r[i]*3);

   while(L
< R)

   {

    int
mid = L + (R-L)/2;

    if(judge(mid))
R = mid;

    else
L = mid+1;

   }

  }

  printf("%d\n", L);

 }

 return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: