POj 2549 sumsets

飞翔

题意:给你一个含有n(n<=1000)个数的数列,问这个数列中是否存在四个不同的数a,b,c,d,使a+b+c=d;若存在则输出最大的d

思路:子集最多有1000C4*4个,时限只有一秒。折半枚举有些讲究,以前折半都是在集合上折半,这次是在等式上。将等式变化为 a + b = d – c,预先算好左右两边并排序。左边全枚举N2,右边二分查找logN2,每枚举一次左边都会在右边二分常数次,所以总的复杂度是O(N2logN2):

AC代码:

#include<stdio.h>
#include<algorithm>
using namespace std;
const int MAX = 1000005;
struct no
{
    int s;
    int x;
    int y;
    bool operator < (const no& b)const
    {
        return s <b.s;
    }
}m1[MAX],m2[MAX];
bool cmp(no a,no b)
{
    return a.s<b.s;
}
bool pd(no a,no b)
{
    return a.x != b.x && a.y != b.y && a.x != b.y && a.y != b.x;
}
int a[2000];
int main( )
{
    int n ;
    while(scanf("%d",&n)!=EOF)
    {
        int ans=-536870912;
        if(n==0)
        break;
        for(int i=0 ; i<n ; i++)
        scanf("%d",&a[i]);
        sort(a,a+n);
        int k=0;
        for(int i=0 ; i<n ; i++)
        for(int j=i+1 ; j<n ; j++)
        {
            m1[k].s=a[i]+a[j];
            m1[k].x=i;
            m1[k].y=j;
            k++;
        }

        int l=0;
        for(int i=0 ; i<n ; i++)
        for(int j=i+1 ; j<n ; j++)
        {
            m2[l].s=a[i]-a[j];
            m2[l].x=i;
            m2[l].y=j;
            l++;
            m2[l].s=a[j]-a[i];
            m2[l].x=j;
            m2[l].y=i;
            l++;

        }
        sort(m1,m1+k);
        for(int i=0 ; i<l ; i++)
        {
            int d=lower_bound(m1,m1+k,m2[i])-m1;
            if(pd(m1[d],m2[i])&&m1[d].s==m2[i].s)
                ans=max(ans,m1[d].s+a[m2[i].y]);
                
        }
        if(ans!=-536870912)
        printf("%d\n",ans);
        else
        printf("no solution\n");

    }
    return 0;

}
View Code

最后进行补充,,,,,这次道题用二分函数进行查找,如果是对结构体的话,要在结构体里面进行重载运算符

猜你喜欢

转载自www.cnblogs.com/shuaihui520/p/9047874.html