HDU-2141(二分搜索)

Can you find it?

Time Limit: 10000/3000 MS (Java/Others)    Memory Limit: 32768/10000 K (Java/Others)
Total Submission(s): 6515    Accepted Submission(s): 1706


Problem Description
Give you three sequences of numbers A, B, C, then we give you a number X. Now you need to calculate if you can find the three numbers Ai, Bj, Ck, which satisfy the formula Ai+Bj+Ck = X.
 

 

Input
There are many cases. Every data case is described as followed: In the first line there are three integers L, N, M, in the second line there are L integers represent the sequence A, in the third line there are N integers represent the sequences B, in the forth line there are M integers represent the sequence C. In the fifth line there is an integer S represents there are S integers X to be calculated. 1<=L, N, M<=500, 1<=S<=1000. all the integers are 32-integers.
 

 

Output
For each case, firstly you have to print the case number as the form "Case d:", then for the S queries, you calculate if the formula can be satisfied or not. If satisfied, you print "YES", otherwise print "NO".
 

 

Sample Input
3 3 3
1 2 3
1 2 3
1 2 3
3
1
4
10
 
Sample Output
Case 1:
NO
YES
NO
 
 
 
斌神讲的二分搜索很好用,二分思想看似简单,要实现起来要注意N多细节,所以,斌神的二分方法是这样实现的,初始的min=0;max=n;而实际的元素最大下标在数组中为n-1,之所以要这么设置,是因为能探测到首末元素,倘若把max=n-1,是无法探测到末元素的。
因为所要搜索的元素可能根本就不在数组元素中,也可能远大于或小于数组中的任意元素,二分查找的最大价值就体现在此,即使无法在队列中找到元素,也要探测到跟该值最接近的元素位置。故,在实现过程中,采取X<=mid,则min=mid反之则反之,结束条件设置为min=mid;这样即可实现以上作用。另外,在每次计算mid时,mid=(max-min)/2+min比较好。
 
这个题目要注意很多地方,首先就是计算它的时间复杂度,如果采取暴力的话,为500^3>10^8,毫无疑问会超时,但是在实现二分上很有技巧,即先设置一个大数组需大于500^2,来存贮a+b,然后将c与该数组中的元素相加。。。判断是否等于X。
还有要注意的是,题目明确说了所有数都为32位int整数,但其实是故意让你掉以轻心,一个数为Int,不代表相加后不会超出范围,所以保险起见,应用long long来定义,但是根据我实测,大数组定义为int也是可以AC的,这可能是数据问题
 
还有个要提醒自己的地方就是 输出的时候竟然丢了冒号,WA了两次才发现这个地方。。。真的。。一定要注意细节。
 
#include <cstdio>
#include <algorithm>
int a[600];
int b[600];
int c[600];
int sum[260000];
int main()
{
    int l,m,n,s;
    int t=1,x;
    while (scanf("%d%d%d",&l,&m,&n)!=EOF)
    {

        for (int i=0; i<l; i++)
        {
            scanf("%d",&a[i]);
        }
        int temp=0;
        for (int j=0; j<m; j++)
        {
            scanf("%d",&b[j]);
            for (int y=0;y<l;y++)
            {
            sum[temp]=a[y]+b[j];
            temp++;
            }
        }
        for (int k=0; k<n; k++)
        {
            scanf("%d",&c[k]);
        }
        std::sort(sum,sum+l*m);
        std::sort(c,c+n);
        scanf("%d",&s);
        printf("Case ");
        printf("%d:\n",t++);
        for (int q=0; q<s; q++)
        {
            int mid;
            scanf("%d",&x);
            bool ans=false;
            for (int w=0;w<n;w++)
            {   int max=m*l,min=0;
                for (;;)
                {
                    mid=(max-min)/2+min;
                    if (mid==min) {break;}
                    if (sum[mid]<=x-c[w])
                    {
                        min=mid;
                    }
                    else max=mid;
                }
                if (sum[mid]==(x-c[w]))
                   {ans=true;break;}
            }
            if (ans) printf("YES\n");
            else printf("NO\n");
        }
    }
    return 0;
}
posted @ 2013-01-22 15:13  KRisen  阅读(293)  评论(0编辑  收藏  举报