现在的位置: 首页 > 综合 > 正文

NWERC 2012 Joint Venture (二分+枚举)

2018年09月23日 ⁄ 综合 ⁄ 共 1449字 ⁄ 字号 评论关闭

题目链接:http://2012.nwerc.eu/en/results/problems/

题目大意:    先给出一个X,单位厘米

                     然后是n条长度为ai的边,单位纳米

                     任取两条边,使得相加后的长度等于X

                     求满足长度等于X且 | L1 L2 | 最大 (既长度只差的绝对值最小) 

                     把两条边从小到大输出,不存在则输出“danger”

解题思路:    先把边从小到大排列,然后分别枚举每一条边

                     看能否找到另一条边与之相加等于X

                     把所有的情况都算出来,并且判断哪种情况边之差的绝对值最小

        剪枝:   其实我们没有必要把所有的边都枚举一次,下面分情况讨论:

                     1.最长和次长的相加小于X,那么说明不存在,直接输出"danger"

                     2.第一条和最后一条边相加大于X,并且中间那条边乘与2小于X,只需要枚举大于中间边:

                         假设X=30,有七条边可供选择  3  5  7  13  15  20  27

                         中间的边 13*2=26<X,第1,2,3条边任意取两条边都不可能相加等于X

                     3.枚举边的时候从最长那条边开始,枚举完那条边可以把那条边去掉,既缩小二分的范围

英文版解题报告:


( 剪枝之后时间复杂度小于O(nlogn) )

代码:

#include <stdio.h>
#include <stdio.h>
#include <algorithm>
using namespace std;
#define MAX 11000000
int a[MAX];
int dichotomy(int num,int n)  //二分搜索,a[]数组有n个元素返回num的下标
{
    int left,middle,right;
    left=0;right=n-1;
    while(left<=right)
    {
        middle=(left+right)/2;
        if(a[middle]==num)  return middle;
        else if(num>a[middle])  left=middle+1;
        else  right=middle-1;
    }
    return -1;   //不存在返回 -1
}

int main()
{
    int pd,x,n,i,j,k,itemp,jtemp,temp,t;
    while(scanf("%d%d",&x,&n)!=EOF)
    {
        k=0;
        x*=10000000;
        for(i=0;i<n;i++)
            scanf("%d",&a[i]);
        sort(a,a+n);
        if(a[n-1]+a[n-2]<x)    //剪枝1
        {
            printf("danger\n");
            continue;
        }
        if(a[0]+a[n]>x&&(2*a[((n-1)/2)+1])<x)    //剪枝2
            k=((n-1)/2)+1;
        for(i=n-1,pd=0;i>=k;i--)
        {
            temp=x-a[i];
            j=dichotomy(temp,i+1);   //剪枝3
            if(j!=-1&&i!=j)
            {
                pd=1;
                itemp=i;
                jtemp=j;
                break;
            }
        }
        if(pd)
        {
            if(itemp<jtemp)
                printf("yes %d %d\n",a[itemp],a[jtemp]);
            else
                printf("yes %d %d\n",a[jtemp],a[itemp]);
        }
        else
            printf("danger\n");
    }
    return 0;
}

注:原创文章,转载请注明出处

抱歉!评论已关闭.