前言
这道题原本老师说是哈希的练习题,结果发现哈希的代码量忒大,然后就用二分了。
正题
有n个赌徒,如果一个赌徒的钱数是其中三个的和那么这个赌徒是赢家,输出最多钱的赢家。
输入输出(建议无视)
Input
输入一个整数n (1<=n<=1000)表示有n个赌徒。
接下去n行各自输入一个整数 x (-536870912
Output
输出每组测试数据的结果。如果没有胜者则输出”no solution”.
Sample Input
5
2
3
5
7
12
5
2
16
64
256
1024
0
Output for Sample Input
12
no solution
解题思路
将4重循环分成两段,变为两个二重循环。第一个二重循环把所有值记录下来,然后第二个二重循环中用二分查找合适的答案。注意由于可能有多组答案相等的数据,由于需要其中去重的性质,所有哈希很麻烦。
代码
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int n,a[1001],S,len,wz;
struct hehe{
int first,last,c;
};//结构体
hehe sum[1000006];
bool f;
int find(int x)//二分查找
{
int mid,l=1,r=len;
while (l<=r)
{
mid=(l+r)/2;
if (sum[mid].c==x) {return mid;}
if (sum[mid].c<x) l=mid+1;
else r=mid-1;
}
return -1;
}
bool cmp(hehe x,hehe y)
{
return x.c<y.c;
}//快排用
int main()
{
while (true)
{
len=0;
f=false;
scanf("%d",&n);
if (n==0) break;
for (int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
sort(a+1,a+1+n);//排序,后面有用
for (int i=1;i<n;i++)
{
for (int j=i+1;j<=n;j++)
{
sum[++len].c=a[i]+a[j];/.记录
sum[len].first=i;//记录去重
sum[len].last=j;
}
}
sort(sum+1,sum+1+len,cmp);
for (int i=n;i>=1;i--)
{
for (int j=1;j<=n;j++)
{
if (i==j) continue;//去重
wz=find(a[i]-a[j]);//查找
if (wz==-1) continue;
while (wz<=len && sum[wz].c==a[i]-a[j] && !f)//前面可能有多组相同答案
{
if (sum[wz].first!=i && sum[wz].last!=j && sum[wz].first!=j && sum[wz].last!=i)//去重
{
S=a[i];
f=true;
break;
//由于前面排了序所有一旦找到就是最大的
}
wz++;
}
if (f) break;
}
if (f) break;
}
if (f) printf("%d\n",S);
else printf("no solution\n");//输出
}
}