ZOJ 1101 Gamblers

来源:互联网 发布:淘宝助理怎样下载宝贝 编辑:程序博客网 时间:2024/06/05 10:14

题目地址:点击打开链接

思路:对于此题,求三个数n1,n2,n3使其之和为另一个数字n。如果存在多种情况,求n值最大的一个。所以首先将所有的数字从小到大排列,从后向前求解,这样就保证求得的第一个赢家为最大值。另外三个数就需要枚举了。三个赌徒,至少有一个在赢家(i)的前面(j),但是由于存在负数,所以另外两个赌徒的编号就有可能在赢家的后面,最初考虑这题的时候,忽略了这点(如果没有负数,三个赌徒肯定都在赢家的前面了)。另外就是如果三个数都要考枚举的话,算法复杂度为O(n^4)。但是由于前面已经对数组进行排序,所以可以先枚举其中两个(j,k),则第三个赌徒的赌注为tmp  = jetton[i] – jetton[j] – jetton[k]; 然后进行二分查找tmp,如果存在,则结束枚举就行了,这样可以降低算法复杂度,不过仍为O(n^3lgn)

AC代码:

#include <iostream>#include <cstdio>#include <algorithm>using namespace std;int a[101000],n,winner;int bsearch(int begin1,int goal){    int left = begin1 + 1,right = n - 1,mid;    while(left <= right)    {        mid = (left + right) / 2;        if(a[mid] == goal)            return mid;        else if(a[mid] < goal)            left = mid + 1;//注意分号敲错        else            right = mid - 1;    }    return 0;}int solve(){    int i,j,k,other,location;    for(i=n-1; i>=0; i--)    {        for(j=i-1; j>=0; j--)//最小的那个数一定比i小        {            for(k=j+1; k < n; k++)//次小的数一定比最小的数大,但不知道和i的大小关系,因为有负数的存在            {                other = a[i] - a[j] - a[k];                location = bsearch(k,other);                if(location && location != i)                {                    winner = i;                    return 1;                }            }        }    }    return 0;}int main(){    int i;    while(scanf("%d",&n) && n)    {        for(i=0; i<n; i++)        {            scanf("%d",&a[i]);        }        sort(a,a+n);        if(solve())//for循环写成一个函数这样就可以一次退出            printf("%d\n",a[winner]);        else            printf("no solution\n");    }    return 0;}



0 0
原创粉丝点击