uva 1335 - Beijing Guard

来源:互联网 发布:surface rt ubuntu 编辑:程序博客网 时间:2024/06/05 03:04

以后需要注意的事情:

在写完后应该先将整个程序检查一遍再交。

思考过程:

分两种情况
1、人数为偶数个
因为只要分成编号为奇数的和编号为偶数的,大家各自拿一部分中的就好了
那么需要的礼物数就是相邻的两个数的和的最大值
既max(a[i]+a[i-1],a[n]+a[1])  i=1,2......,n-1,n
2、人数为奇数个
从1给礼物,一直给到n-1,到给n礼物的时候需要既不跟1号的相同,也不和n-1号的相同。
已经想不到办法了,这时可以尝试二分一下答案。
二分答案以后,我们发现现在我们需要的是让1号和n-1号守卫拥有的相同的礼物尽可能多
那么可以采用贪心的策略
1号守卫给1-a[1]号礼物
后面的2-n-1号守卫,偶数号在不冲突的前提下尽可能给小号的礼物,奇数号的守卫在不冲突的前提下尽可能给大号的礼物。这样可以使1号和n-1号守卫拥有的相同的礼物尽可能多。
最后检查一下既不与1号冲突,又不与n-1号冲突的礼物还有多少个,是否大于n号守卫的需求。然后根据检查调整二分的范围。

画一下图就可以知道礼物的分布是一整段一整段的,因此只需要用a1,b1,a2,b2四个变量来表示礼物发放的状态。所以发一次礼物的时间是O(n),整个算法的时间是O(N*logN).


初始状态:

f[1].b2 = 0;
f[1].a2 = a[0];
f[1].b1 = a[1];
f[1].a1 = m-f[1].b1-f[1].a2;
状态转移:

偶数:

f[i].b2 = min(f[i-1].b2, l);
l = l - f[i].b2;
f[i].a2 = f[i-1].a2+f[i-1].b2-f[i].b2;
f[i].b1 = min(f[i-1].b1, l);
f[i].a1 = m - f[i].a2 - f[i].b1 - f[i].b2;

奇数

f[i].a1 = min(f[i-1].a1, l);
l = l - f[i].a1;
f[i].b1 = f[i-1].a1+f[i-1].b1-f[i].a1;
f[i].a2 = min(f[i-1].a2, l);
f[i].b2 = m-f[i].a1-f[i].b1-f[i].a2;


我的代码:

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
using namespace std;
struct grid
{
int a1,b1,a2,b2;
};
grid f[200000];
int a[200000];
int n,m,mmax,mmin;
int min(int x,int y)
{
return x>y?y:x;
}
int max(int x,int y)
{
return x>y?x:y;
}
bool check(int m)
{
int l=0;
if (f[n-2].a2+f[n-2].b2>a[0])
{
l = min(f[n-2].a2+f[n-2].b2-a[0], f[n-2].a2);
l += f[n-2].a1;
}
else
{
l = min(f[n-2].a1, m-a[0]);
}
if (l>=a[n-1])
return true;
else return false;
}
int main()
{
int i,l;
while (scanf("%d",&n))
{
if (n==0)
break;
for (i=0;i<n;i++)
scanf("%d",&a[i]);
mmax=mmin=0;
for (i=1;i<n;i++)
mmax = max(mmax,a[i]+a[i-1]);
mmax = max(mmax,a[0]+a[n-1]);
if (n%2 == 0)
{
printf("%d\n",mmax);
continue;
}
if (n == 1)
{
printf("%d\n",a[0]);
continue;
}
mmin = mmax;
mmax *= 2;
while (mmin<mmax)
{
m = (mmin+mmax)/2;
f[1].b2 = 0;
f[1].a2 = a[0];
f[1].b1 = a[1];
f[1].a1 = m-f[1].b1-f[1].a2;
for (i=2;i<=n-2;i++)
{
l = a[i];
if (i%2 == 0)
{
f[i].a1 = min(f[i-1].a1, l);
l = l - f[i].a1;
f[i].b1 = f[i-1].a1+f[i-1].b1-f[i].a1;
f[i].a2 = min(f[i-1].a2, l);
f[i].b2 = m-f[i].a1-f[i].b1-f[i].a2;
}
else
{
f[i].b2 = min(f[i-1].b2, l);
l = l - f[i].b2;
f[i].a2 = f[i-1].a2+f[i-1].b2-f[i].b2;
f[i].b1 = min(f[i-1].b1, l);
f[i].a1 = m - f[i].a2 - f[i].b1 - f[i].b2;
}
}
if (check(m))
mmax = m;
else mmin = m+1;
}
printf("%d\n",mmax);
}
return 0;
}

0 0
原创粉丝点击