首页 > 代码库 > uva 10487 Closest Sums (遍历&二分查找&&双向查找)

uva 10487 Closest Sums (遍历&二分查找&&双向查找)

题目大意:先给定n个数字,现在要求算出这n个数字的两两之和保存到sum数组,然后在给定m个数,要求找到和每一个数最接近的sum[i];

挨个计算每个属于其他数之间的sum,然后排序;

查找时有两种方法:二分查找&&双向查找;当然二分查找的效率比后者高了很多,但是都能AC。

提供一条新思路,并不一定非要用二分。

双向查找:

#include<stdio.h>
#include<algorithm>
#include<stdlib.h>
using namespace std;
int n,m;
int a[1000010];
int a1[1010];
int ans;
int main()
{
    int cnt=0;
    while(scanf("%d",&n)!=EOF&&n)
    {
        cnt++;
        printf("Case %d:\n",cnt);
        for(int i=0; i<n; i++)
        {
            scanf("%d",&a1[i]);
        }
        int t=0;
        for(int i=0; i<n; i++)
        {
            for(int j=i+1; j<n; j++)
            {
                int temp=a1[i]+a1[j];
                a[t++]=temp;
            }
        }
        sort(a,a+t);

        scanf("%d",&m);
        for(int k=0; k<m; k++)
        {
            int b;
            scanf("%d",&b);
            int bb;
            for(int i=0,j=t-1; i<t/2,j>=t/2; i++,j--)//双向查找;
            {
                if(a[i]>=b)
                {
                    bb=i;
                    break;
                }
                if(a[j]<=b)
                {
                    bb=j;
                    break;
                }
            }
            if(a[bb]==b)
                ans=a[bb];
            else
            {
                if(a[bb]<b&&bb!=t-1)
                {
                    if(a[bb+1]-b>b-a[bb])
                        ans=a[bb];
                    else
                        ans=a[bb+1];
                }
                else if(a[bb]>b&&bb!=0)
                {
                    if(b-a[bb-1]>a[bb]-b)
                        ans=a[bb];
                    else
                        ans=a[bb-1];
                }
                else
                    ans=a[bb];
            }
            printf("Closest sum to %d is %d.\n",b,ans);
        }
    }
    return 0;
}

二分查找:

#include <algorithm>  
#include <iostream>  
#include <cstring>  
#include <string>  
#include <vector>  
#include <cstdio>  
#include <stack>  
#include <queue>  
#include <set>  
using namespace std;  
#define MAXN 1010  
  
int n , m , len;  
int num_n[MAXN] ,num_m[MAXN];  
int sum[1000010];  
//二分查找  
void Binary_Search(int a){  
    int left , right , mid , ans;  
    left = 0 ; right = len-1;  
    while(1){  
        if(right-left == 1){  
            ans = (sum[right]-a)<(a-sum[left])?sum[right]:sum[left];  
            break;  
        }  
        mid = (left+right)/2;  
        if(sum[mid] > a)  right = mid;  
        if(sum[mid] < a)  left = mid;  
        if(sum[mid] == a) {ans = a ; break;}  
    }  
    printf("Closest sum to %d is %d.\n" , a , ans);  
}  
  
void solve() {  
    int i , j , k;  
    for(i = 0 , k = 0 ; i < n ; i++){  
        for(j = i+1 ; j < n ; j++)  
            sum[k++] = num_n[i]+num_n[j];  
    }  
    len = k ; sort(sum , sum+k);  
    for(i = 0 ; i < m ; i++)  
        Binary_Search(num_m[i]);   
}  
  
int main() {  
    //freopen("input.txt" , "r" , stdin);  
    int cnt = 1;  
    while(scanf("%d%*c" , &n) && n){     
        for(int i = 0 ; i < n ; i++)  
            scanf("%d%*c" , &num_n[i]);  
        scanf("%d%*c" , &m);  
        for(int i = 0 ; i < m ; i++)  
            scanf("%d%*c" , &num_m[i]);  
        printf("Case %d:\n" , cnt++);  
        solve();  
    }  
    return 0;  
} 

好像也快不了多少……

下面这个快:

#include<cstdio>  
#include<cstdlib>  
#include<algorithm>  
using namespace std;  
#define sf scanf  
#define pf printf  
const int INF=0x3f3f3f3f;  
  
int a[1005];  
int cas = 0, n, m, query, closest, diff, i, j;  
  
inline void find()  
{  
    if (j == n || j != i + 1 && diff - a[j - 1] < a[j] - diff)  
    {  
        if (diff - a[j - 1] < abs(closest - query))  
            closest = a[i] + a[j - 1];  
    }  
    else  
    {  
        if (a[j] - diff < abs(closest - query))  
            closest = a[i] + a[j];  
    }  
}  
  
int main()  
{  
    while (sf("%d", &n), n)  
    {  
        for (i = 0; i < n; ++i)  
            sf("%d", &a[i]);  
        sort(a, a + n);  
        sf("%d", &m);  
        pf("Case %d:\n", ++cas);  
        while (m--)  
        {  
            sf("%d", &query);  
            closest = INF;  
            for (i = 0; i < n - 1; ++i)  
            {  
                diff = query - a[i];  
                j = lower_bound(a + i + 1, a + n, diff) - a;  
                find();  
            }  
            pf("Closest sum to %d is %d.\n", query, closest);  
        }  
    }  
    return 0;  
}  


uva 10487 Closest Sums (遍历&二分查找&&双向查找)