题目:给你n个数让你在里面找到会不相同的4个数a,b,c,d,使得 d = a + b + c。
分析:数学题,散列表。这是一个优化问题。
方法1:暴力法;
先排序,然后直接利用四层循环求解,找到解后直接跳出,也可以以利用二分代替最后一层循环;
这种方法,如果遇到特殊的数据就会TLE;
方法2:分步计算;
将等式转化为 d - a = b + c;我们分别求解两边的结果,然后找到结果相同的值即可;
查找方法,可以使用散列表储存b + c 或 a + b 的值,供另一边查找;也可存进数组,二分查找。
说明:存储时记录计算的两个元素的下标,每个数字都不同;注意哈希值可能为负。
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;
/* Hash define */
#define nodesize 500000
#define hashsize 1000
typedef struct node
{
int value,l,r;
node* next;
}list;
list dict[nodesize+1];
list* head[hashsize+1];
class Hash
{
private:
int size;
public:
Hash(){size = 0;memset( head, 0, sizeof(head) );}
int hash( int value ) {return abs(value)%hashsize;}
void insert( int value, int i, int j ) {
int id = hash(value);
dict[size].value = value;
dict[size].l = i;
dict[size].r = j;
dict[size].next = head[id];
head[id] = &dict[size ++];
}
int find( int value, int i, int j ) {
int id = hash(value);
for ( list* p = head[id] ; p ; p = p->next )
if ( value == p->value )
if ( i != p->r && i != p->l && j < p->l )
return true;
return false;
}
};
/* Hash end */
int data[1002];
int main()
{
int n;
while ( cin >> n && n ) {
for ( int i = 1 ; i <= n ; ++ i )
cin >> data[i];
sort( data+1, data+n+1 );
Hash hash;
for ( int i = 1 ; i <= n ; ++ i )
for ( int j = i+1 ; j <= n ; ++ j )
hash.insert( data[i]+data[j], i, j );
int flag = 0;
for ( int i = n ; i >= 1 ; -- i ) {
for ( int j = 1 ; j <= n ; ++ j )
if ( i != j && hash.find( data[i]-data[j], i, j ) ) {
cout << data[i] << endl;
flag = 1; break;
}
if ( flag ) break;
}
if ( !flag ) cout << "no solution" << endl;
}
return 0;
}