题目大意:先给定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 (遍历&二分查找&&双向查找)
原文地址:http://blog.csdn.net/u013382399/article/details/24843139