AYITACM2016省赛第三周M - 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 ?nally 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 di?erent 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 di?erent 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 ?rst

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个人,每个人都想要礼物,相邻两个人会聊天炫耀礼物,不能让他们礼物相同,问至少要多少个礼物才能满足条件。

思路:

偶数个人的话,礼物个数即为最大的两个邻居想要礼物数之和。

奇数个人的话比较复杂,二分搜索最小礼物个数p,将礼物分为左右两堆,左堆放x,右堆y(x+y=p),left[i],right[i]分别表示第i个人拿走了左,右两堆多少个礼物,让奇数号的人尽量从右边拿,偶数号的人尽量从左边拿,第一个人拿走了左边所有的x,最后只要再判断一下最后一个人是否拿过左边的礼物就行。

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<string>
using namespace std;
int a[100010],left[100010],right[100010],n;
int judge(int p)
{
    int x,y,i;
    left[1]=a[1],right[1]=0;
    x=a[1],y=p-a[1];//将礼物分成两堆
    for(i=2; i<=n; i++)
    {
        if(i%2==0)//如果是第偶数个保安
        {
            left[i]=min(a[i],x-left[i-1]);//尽量从左边拿,判断上一个人留下的礼物是否够,如果不够再拿右边
            right[i]=a[i]-left[i];//记录在右边拿了几个礼物
        }
        else
        {
            right[i]=min(a[i],y-right[i-1]);//尽量从右边拿,判断目前礼物是否够
            left[i]=a[i]-right[i]; //记录还需从右边拿几个
        }
    }
    return left[n]==0;//判断最后一个人是否拿过左边的礼物
}
int main()
{
    while(~scanf("%d",&n)&&n)
    {
        int i,l=0,r=0,m;//l为二分的下限,r为上限
        for(i=1; i<=n; i++)
        {
            scanf("%d",&a[i]);
            r=max(r,a[i]*3);//r最大为需要礼物最多的保安的三倍,
        }
        if(n==1)//如果只有一个保安,礼物数量就是他需要的数量
        {
            printf("%d\n",a[1]);
            continue;
        }
        a[n+1]=a[1];//因为是环形,所以需要考虑最后一个和第一个的关系
        for(i=1; i<=n; i++)
            l=max(l,a[i]+a[i+1]);//二分下限为相邻的保安礼物之和的最大值
        if(n%2==1)  //如果保安数量为奇数
        {
            while(l<=r)   //e二分求最优解
            {
                m=(l+r)/2;
                if(judge(m))  //如果礼物够分,就再减少一个礼物
                    r=m-1;
                else   //如果礼物不够分,就增加礼物
                    l=m+1;
            }
            printf("%d\n",r+1);//最后输出礼物数量
        }
        else //如果保安数量为偶数,最优解就是相邻保安礼物之和的最大值
            printf("%d\n",l);
    }
    return 0;
}

时间: 2024-08-29 01:47:12

AYITACM2016省赛第三周M - Beijing Guards(贪心+二分)的相关文章

AYITACM2016省赛第三周 L - Anniversary party(树形dp)

Description There is going to be a party to celebrate the 80-th Anniversary of the Ural State University. The University has a hierarchical structure of employees. It means that the supervisor relation forms a tree rooted at the rector V. E. Tretyako

AYITACM2016省赛第三周I - Optimal Array Multiplication Sequence(dp)

矩阵最少乘法 题意: 给你2个矩阵A.B,我们使用标准的矩阵相乘定义C=AB如下: A阵列中栏(column)的数目一定要等于B阵列中列(row)的数目才可以做此2阵列的相乘.若我们以rows(A),columns(A)分别代表A阵列中列及栏的数目,要计算C阵列共需要的乘法的数目为:rows(A)*columns(B)*columns(A).例如:A阵列是一个10x20的矩阵,B阵列是个20x15的矩阵,那么要算出C阵列需要做10*15*20,也就是3000次乘法. 要计算超过2个以上的矩阵相乘

uva 1335 Beijing Guards(二分)

uva 1335 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

第二第三周暑期集训总结

##第二第三周暑期集训总结在第二第三周中,我主要看了状压DP,数位DP,树状DP的主要内容.同时,在做训练赛的过程中,发现一些知识点掌握的不好,于是又回头复习了一下,包括图的一些基本概念,最短路算法,并查集,最小生成树,图的存储方法(矩阵,邻接表(数组)).还有很关键的一件事就是参加了今年的CCPC网络选拔赛.####状压DP刚开始看的时候,我觉得状压DP很难.在恶补了位运算的知识后,我又自己敲了一遍代码,突然有一种茅塞顿开的感觉.这是我对状压DP的理解:状压DP其实也没什么深奥的,就是利用位运

第三周活动进度

学习进度表:   第三周内容 时间 周一(4:10-6:00)上课,周二晚上(8:00-9:00),周四晚上(8:00-8:30),周四下午(4:10-6:00)javaweb课程 代码行数 200行 发博客量 3篇 了解到的知识 随机数的产生,四则运算的开发思路(分解),简单的数据库创建表. 周活动详细记录表: 日期/内容 写代码 上网查方法 上课 看书(构建执法) 3.6 2小时(150行)大概完成   2小时   3.7   查询缺失功能的方法   1小时 3.8         3.9

20145207《Java程序设计》第三周学习总结

20145207<Java程序设计>第三周学习总结 教材学习内容总结 这部分可能要扒一些课本而上的东西了.在第三章中,知道了Java可区分为基本类型和类类型两大类型系统,其中类类型也称为参考类型.在这一周主要学习了类类型. 对象(Object):存在的具体实体,具有明确的状态和行为 类(Class):具有相同属性和行为的一组对象的集合,用于组合各个对象所共有操作和属性的一种机制. 简单来说,类是对象的设计图,对象是类的实例. 要深刻理解对象的含义,例如Clothes c1 = new Clot

每周学习进度--第三周

  第三周 所花时间(包括上课) 300min 代码量 258 博客量 2 了解到的知识点 初步了解了如何做软件需求分析

20145326蔡馨熠《信息安全系统设计基础》第三周学习总结

教材学习内容总结 书上有的内容我就不重复赘述了,只需要将部分重要的知识点归纳总结一下. 1.进制 二进制.八进制.十进制.十六进制(转换:以二进制作为中间变量) 2.字 每台计算机都有一个字长,指明整数和指针数据的大小. 虚拟地址是以这样的一个字来编码的,字长决定虚拟地址空间的最大范围. 3.字节顺序 小端法——在存储器中按照从最低有效字节到最高有效字节的顺序存储对象. 大端法——从最高有效字节到最低有效字节的顺序存储. 4.布尔代数 (1)二进制值是计算机编码.存储.操作信息的核心(0.1),

马哥2016全新Linux+Python高端运维班第三周作业作答

                    马哥2016全新Linux+Python高端运维班第三周作业                                           1.列出当前系统上所有已经登录的用户的用户名,注意:同一个用户登录多次,则只显示一次即可.     [[email protected] ~]# who | awk '{print $1 $NF}'| uniq -d     [[email protected] ~]# who     yicx     :0