首页 > 代码库 > UVa 11057 - Exact Sum

UVa 11057 - Exact Sum

题目:已知n个数a[1..n],还有另一个数M,在前n个数中找到差值最小的两个数使得他们的和是M。

分析:数学。排序,找M/2。然后向两边分别扩展即可。

            设a[s]是第一个大于M/2的数字,

            如果M是偶数,并且存在至少两个M/2,则a[s-1]、a[s-2]一定是M/2;

            否则a[s-1] <= M/2 ,a[s] > M,从这两点向两边扩展即可(l = s-1,r = s):

                    若a[l]+a[r] > M,l 向左移动(l --)

                    若a[l]+a[r] < M,r 向右移动(r ++)

                    若 a[l]+a[r] = M,则就是解,这是a[l]的a[r]差最小(因为,差值和r与l的插值正相关)。

说明:╮(╯▽╰)╭l --写成了r ++RE好几次。

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstdio>

using namespace std;

int data[10012];
int bs( int r, int key )
{
	int mid,l = 0;
	while ( l < r ) {
		mid = l+(r-l)/2;
		if ( data[mid] <= key )
			l = mid+1;
		else r = mid;
	}
	return r;
}

int main()
{
	int n,sum;
	while ( ~scanf("%d",&n) ) {
		for ( int i = 0 ; i < n ; ++ i )
			scanf("%d",&data[i]);
		data[n] = 1000002;
		scanf("%d",&sum);
		sort( data, data+n );
		int s = bs( n, sum/2 );//找到第一个大于sum/2的值 
		if ( s >= 2 && data[s-1]+data[s-2] == sum ) 
			printf("Peter should buy books whose prices are %d and %d.\n\n",data[s-2],data[s-1]);
		else {
		int l = s-1,r = s;
			while ( l >= 0 && r < n ) {
				if ( data[l]+data[r] == sum ) {
					printf("Peter should buy books whose prices are %d and %d.\n\n",data[l],data[r]);
					break;
				}else if ( data[l]+data[r] < sum )
					r ++;
				else l --;
			}
		}
	}
	return 0;
}