原题地址:http://acm.hdu.edu.cn/showproblem.php?pid=2141
题目原文:
Can you find it?
Time Limit: 10000/3000 MS (Java/Others) Memory Limit: 32768/10000 K (Java/Others)
Total Submission(s): 45692 Accepted Submission(s): 11064
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
题目大意:
第一行输入L,N,M , 接下来各行分别输入L, N, M个整数组成a[i], b[j], c[k], 紧接着输入一个整数S,下面再输入S行整数x,要求a[i] + b[j] + c[k] = x. 如果能够等式成立,输出YES,不成立输出NO.
解题思路:
根据题目数值范围分析,都在int32内。将等式 ai + bj + ck = x 转化成 ai + bj = x - ck; 因为a、b数组范围在500内,不算大,可以先用O(500^2)复杂度将a、b数组合并成一个数组ab,紧接着遍历c数组利用二分查找ab数组使得ab[?]==x-c.
AC代码:
#include <cstdio>
#include <algorithm>
#include <functional>
using namespace std;
const int N = 501;
const int M = 1001;
const int L = N * N;
const char *NO = "NO";
const char *YES = "YES";
int g_la, g_lb, g_lc; // [1, 500]
int g_ls; // [1, 1000]
int g_lab; // [1, 250000]
int g_a[N];
int g_b[N];
int g_c[N];
int g_x[M];
int g_ab[L];
// a + b + c = x ---> a + b = x - c, 合并ab后,ab = x - c
void mergeAB()
{
int i, j;
for (g_lab = 0, i = 0; i < g_la; i++)
{
for (j = 0; j < g_lb; j++)
{
g_ab[g_lab++] = g_a[i] + g_b[j];
}
}
sort(g_ab, g_ab + g_lab, less<int>());
}
// 二分查找ab, 返回大于等于x-c的第一个下标, 如果不等于就返回(负数 - 1)
int bsearch(int arr[], int len, int val)
{
// 保证arr已经升序排序
int left = 0;
int right = len - 1;
int middle;
while (left <= right)
{
middle = (left + right) >> 1;
if (arr[middle] < val) left = middle + 1;
else right = middle - 1;
}
// return left;
if (arr[left] == val) return left;
else return -left - 1;
}
int main()
{
int I = 1;
while (scanf("%d%d%d", &g_la, &g_lb, &g_lc) != EOF)
{
int i, j;
for (i = 0; i < g_la; i++) scanf("%d", &g_a[i]);
for (i = 0; i < g_lb; i++) scanf("%d", &g_b[i]);
for (i = 0; i < g_lc; i++) scanf("%d", &g_c[i]);
scanf("%d", &g_ls);
for (i = 0; i < g_ls; i++) scanf("%d", &g_x[i]);
printf("Case %d:\n", I++);
mergeAB();
for (i = 0; i < g_ls; i++)
{
for (j = 0; j < g_lc; j++)
{
if (bsearch(g_ab, g_lab, g_x[i] - g_c[j]) >= 0)
{
printf("%s\n", YES);
break;
}
}
if (j >= g_lc) printf("%s\n", NO);
}
}
return 0;
}