UVALive 3177 && uva 1335 Beijing Guards (贪心+二分)

题意:给定n个守卫战成一圈,每个守卫要r个礼物,然后问需要几种礼物分配给他们才能使得相邻两个守

      卫礼物都不同

思路:

1、 当n为偶数的时候,ans = max(p[i]+p[i+1]),可以自己画个图验证;

2、 当n为奇数的时候就不满足了,那么我们可以利用二分答案然后判断从而求出最小值。假设有p种礼

物,那么设第一个人的礼物为1~r1,那么不难发现最有的分配的策略一定是这样的:除1以外的其他人,

编号为偶数的人尽量往前取,编号数的人尽量往后取。这样我们只要最后判断第n个人是否与第一个

人有冲突即可。

3、 由于题目并没有要我们输出实际的方案,那么我们只需要记录每个人在[1,r1]和[r1+1,n]这个范围内

取了几个,最后判 断第n个人是否有取[1,r1]范围内的数即可。

4 、注意对于n = 1的情况需要特判。


#include<cstdio>
#include<algorithm>
using namespace std;

int p[100010];
int le[100010],ri[100010];
int n;

//le[i]为第i个人拿的左边的礼物总数
bool test(int u)  //测试u个礼物是否足够
{
    le[1]=p[1],ri[1]=0;
    int x=p[1],y=u-p[1];  //x?y?
    for(int i=2;i<=n;i++)
    {
        if(i%2==0)     //尽量拿左边的礼物
        {
            le[i]=min(p[i],x-le[i-1]);
            ri[i]=p[i]-le[i];
        }
        else            //尽量拿右边的礼物
        {
            ri[i]=min(p[i],y-ri[i-1]);
            le[i]=p[i]-ri[i];
        }
    }
    return le[n]==0;
}

int main()
{
    while(scanf("%d",&n)&&n)
    {
        for(int i=1;i<=n;i++)
            scanf("%d",&p[i]);
        if(n==1)    //注意特判n=1
        {
            printf("%d\n",p[1]);
            continue;
        }
        p[n+1]=p[1];
        int L=0,R=0,mid;
        for(int i=1;i<=n;i++)
        {
            L=max(L,p[i]+p[i+1]);  //最小范围
            R=max(R,p[i]);
        }
        if(n%2==0)
        {
            printf("%d\n",L);
            continue;
        }
        else
        {
            R=3*R;     //3倍最大范围
            while(L<R)
            {
                mid = L+(R-L)/2;
                if(test(mid))
                    R=mid;
                else L=mid+1;
            }
            printf("%d\n",L);
        }
    }
    return 0;
}



感想:

真的没想出来,看了题解还是有点不大明白= =,正在慢慢领悟中。。。。

参考链接:http://tech.ddvip.com/2013-11/1384268234205850.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值