TK题库 1097 赌徒(暴力+二分)

原题

赌徒

Time Limit: 1 Sec Memory Limit: 32 MB


Description

有n个赌徒打算赌一局。规则是:
每人下一个赌注,赌注为非负整数,且任意两个赌注都不相同。胜者为赌注恰好是其余任意三个人的赌注之和的那个人。如果有多个胜者,我们取赌注最大的那个为最终胜者。
例如,A,B,C,D,E分别下赌注为2、3、5、7、12,最终胜者是E,因为12=2+3+7。

Input

输入包含多组测试数据。每组首先输入一个整数n(1<=n<=1000),表示赌徒的个数。
接下来n行每行输入一个非负整数b(0<=b<32768),表示每个赌徒下的赌注。
当n=0时,输入结束。

Output

对于每组输入,输出最终胜者的赌注,如果没有胜者,则输出no solution。
Sample Input
5
2
3
5
7
12
5
2
16
64
256
1024
0

Sample Output

12
no solution

涉及知识及算法

二分查找,暴力求解
本题关键是对所有可能情况的暴力枚举,尽可能的优化代码减少不必要的计算。
首先,将赌注排序,题目要找可能的最大解,故和赌注 i 应该从后往前枚举。
(注:此处的 i ,j,k,t 都指的是排序后的位置。)
接下来分别是三人各自的赌注,我们可以把它分为较小的赌注 j,较中间的赌注 k,较大的赌注 t 三部分。
较小的应小于中间的 j+1<=k 中间的应小于较大的 k+1<=t
我们用三重循环组合 i,j,k ,用减法求出 “准 t” 看是否能在k+1~n之中找到它即可。

代码

#include <iostream>
#include <cstring>
#include <cstdio>
#include <string>
#include <algorithm>
using namespace std;
int n,t,ans;
int a[1005];
//二分查找位置
int bin(int l,int h,int k)
{
    int m;
    while(l<h)
    {
        m=(l+h)/2;
        if(k==a[m])
        {
            return m;
        }
        else if(k<a[m])
        {
            h=m;
        }
        else
        {
            l=m+1;
        }
    }
    return -1;
}
 
void Find()
{
    //开启无脑循环
    //i为和
    for(int i=n-1;i>=0;i--)
    {
        //j为第一个数,j<i保证a[j]<a[i]
        for(int j=0;j<i;j++)
        {
            //k为第二个数,
            for(int k=j+1;k<i;k++)
            {
                //t为准~第三个数
                t=a[i]-a[k]-a[j];
                if(bin(k+1,i,t)!=-1)
                {
                    ans=i;
                    return ;
                }
            }
        }
    }
}
int main()
{
    //freopen("in.txt","r",stdin);
    while(scanf("%d",&n)&&n)
    {
        for(int i=0;i<n;i++)
        {
            scanf("%d",a+i);
        }
        sort(a,a+n);
        ans=0;
        Find();
        if(ans)
        {
            printf("%d\n",a[ans]);
        }
        else
        {
            printf("no solution\n");
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值