Angry Cows总结_2016.2.28

来源:互联网 发布:中国水污染地图数据库 编辑:程序博客网 时间:2024/06/05 16:50

     AngryA:

题目大意:有一些干草堆,它们放在一个数轴上,用一头奶牛砸到任意一个干草堆上,会发生连锁爆炸,导致R+1(R是预先给出的)半径内的干草堆爆炸,然后被炸的干草堆也会发生连锁反应,导致以他为圆心,半径为上一个干草堆的半径+1范围内的草堆爆炸。问最多能炸多少个干草堆。

数据分析:这题的数据范围比较小,干草堆的坐标位置为0~1,000,000,000,但最多只有100个干草堆,所以直接模拟就可以了。

具体做法:这题由于坐标大,草堆少,所以我们可以一个一个草堆枚举(即枚举爆炸点),分别向左向右一个一个草堆模拟(注意不是一个一个坐标),找到当前草堆能炸到的最左(右)的一个草堆,再以它为圆心,向左(右)重复此步骤(注意半径应该递增),直到一个草堆也炸不到为止。再统计左右共炸了多少个草堆即可。

时间复杂度:O(N2) , N≤100 , O≤104

参考程序(我自己写的):


出现的错误:模拟的半径不记得递增了,编程不细心。

AngryB:

题目大意:与第一题类似,但这题是使用K(预先给出)头奶牛,引爆所有的干草堆。注意:这题中的干草堆并不会发生连锁爆炸,只有在以放置奶牛为圆心的、半径为R(所有奶牛半径都一样)范围内的干草堆会爆炸。另外这题中还说明了,奶牛可以被放置在数轴上的任意位置(整数),求最少的r值为多少。

数据分析:因为这一题的干草堆的个数最多为50000个,而且干草堆的坐标位置为MAXN:0~1,000,000,000,故直接枚举是不可能过的了,而且还有K(1≤K≤10)头奶牛。但仔细一看,发现这题有点像NOIP提高组的stone,可以用二分答案,二分奶牛爆炸的半径R。

具体做法:这题应该二分奶牛的爆炸半径R,然后是不是还要枚举爆炸点呢?当然不是,因为这题并不会连锁爆炸,所以我们可以一个一个的枚举奶牛爆炸的左端点,再加上R*2,即为放置奶牛在此所能达到的最远坐标。首先,为了将所有干草堆炸完,第一个干草堆一定是要作为一个左端点的(这样才能炸到它并尽量炸到靠后的干草堆),然后再逐个向后找,直到超出前一个奶牛的爆炸范围,就再将这个干草堆作为左端点,重复刚才的步骤,并记录共用的奶牛的个数,判断是否超过了给定的K,然后就是和二分一样的了。

时间复杂度:枚举:O(MAXN*N*K) , O>108

        二分答案:O(log2(MAXN)*N) , O<108

参考程序:

#include<iostream>#include<algorithm> using namespacestd; int main(){       int n,k,Max=-10000,pos[50004];       cin >> n >> k;       for (int i=0;i<n;i++) cin >> pos[i];       sort(pos,pos+n);       int l,r,last,mid,use;       l=-1;r=(pos[n-1]-pos[0])/k+3;       while (l+1<r)       {              use=1;              mid=(l+r)/2;              last=0;              for (int j=0;j<n;j++)                     if (!(pos[last]+2*mid>=pos[j])) last=j,use++;              if (use<=k) r=mid;              else l=mid;       }       if (r>Max) Max=r;       cout << Max;}


出现的错误:首先是没看清题目,以为这一题能够连环爆炸,所以完全错了,提交后才发现。然后第二遍就是因为不常编二分,所以不太熟,刚开始while总是死循环,其实二分应该保持一边不合法(无法炸完),一边合法,继续条件为(l+1<r),这样才能避免死循环。

2 1
原创粉丝点击