1. 题目
Loongint的旅行安排
【Description】
Loongint和MM要出去旅行,出行前规划旅行方案时,MM给Loongint出了一个难题。她说,在她心中,不同的地方能给她不同的感受,而感受可以用喜爱值Li表示出来,她希望这次旅行能正好得到W的喜爱值。为了考验Loongint是否爱他,她只是给了Loongint所有的Li和W值,却并不告诉Loongint哪个是哪个…Loongint手头比较紧,只能支付去三个地方的费用,所以Loongint必须从这些数中找出三个Li和一个W,并且使W尽量的大。
Loongint一心想和MM去旅行,哪里有时间想这个问题,所以,交给了Hzoi同仁的你…
【Input】
输入数据有两组(为了防止No Solution骗分J)。
对于每一组,第一行n表示有n个数值,接下来n行为每个数值的大小。
【Output】
两组输出。分别为每组的答案。如果可以找出三个Li和一个W,那么就输出最大的W,如果不能,就输出No Solution。
【Sample Input】
4
5
5
5
5
4
1
2
3
6
【Sample Output】
No Solution
6
【Hint】
对于30%的数据,1=<n<=100
对于100%的数据,1<=n<=1000,Li和W都属于[-536870911,536870911]
2. 算法
其实这是一个 HASH ,首先将任意两个数的和处理出来,然后用 HASH 存储这个和是否存在,这样查找的速度才可以满足要求。
枚举 w ,枚举一个 L[i] ,然后,当他们两个的差是存在的,并且加出这个差的那两个数中没有你枚举的那个 L[i] ,就是答案了。
3. 注意事项
注意记录每个和由哪两个数加出来。
还有,此处的 HASH 函数必须是那个和 mod 999983 的余数。。。。。。因为出题人的标程是这样的,坑爹啊!
4. 代码
HASH (Liukeke)
program liukeke;
type pointer=^rec;
rec=record
a,b,data:longint;
next:pointer;
end;
var
hash:array[-999983..999983] of pointer;
num:array[0..1000] of longint;
p:pointer;
n,zu,i,j,ans:longint;
function find(x:longint):boolean;
var
p:pointer;
temp:longint;
begin
temp:=x mod 999983;
p:=hash[temp];
while p<>nil do
begin
if (p^.a<>num[i])and(p^.b<>num[i])and(p^.a<>num[j])and(p^.b<>num[j])then
if p^.data=x then exit(true);
p:=p^.next;
end;
exit(false);
end;
begin
assign(input,'plan.in');reset(input);
assign(output,'plan.out');rewrite(output);
for zu:=1 to 2 do
begin
readln(n);
for i:=1 to n do
readln(num[i]);
for i:=-999983 to 999983 do
hash[i]:=nil;
for i:=1 to n do
for j:=i+1 to n do
begin
new(p);
p^.a:=num[i];
p^.b:=num[j];
p^.data:=num[i]+num[j];
p^.next:=hash[(num[i]+num[j]) mod 999983];
hash[(num[i]+num[j])mod 999983]:=p;
end;
ans:=-536870912;
for i:=1 to n do
for j:=1 to n do
if i<>j then
if find(num[i]-num[j]) and (num[i]>ans)
then ans:=num[i];
if ans<>-536870912 then
writeln(ans)
else writeln('No Solution');
end;
close(input);
close(output);
end.