ZOJ1101-赌徒【二分查找】

针对一道寻找赌徒中赢家的问题,使用二分查找而非哈希方法进行解答。问题要求从n个赌徒中找出其财富等于其他任意三名赌徒财富之和的最大赢家。通过将四重循环拆分为两个双重循环并利用二分查找,有效解决了去重问题,并找到了最大赢家。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

这道题原本老师说是哈希的练习题,结果发现哈希的代码量忒大,然后就用二分了。


正题

有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");//输出
    }
}

转载于:https://www.cnblogs.com/sslwyc/p/9218581.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值