题目大意:先给定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; }