zoukankan      html  css  js  c++  java
  • 和为0的4个值

    试题描述

     给定4个n(1<=n<=4000)元素集合A,B,C,D,要求分别从中选取一个元素a,b,c,d,使得a+b+c+d=0。问:有多少种选法?

    例如,A={-45,-41,-36,26,-32,100000},B={22,-27,53,30,-38,-54},C={42,56,-37,-75,-10,-6},D={-16,30,77,-46,62,45},则有5种选法:(-45,-27,42,30),(26,30,-10,-46),(-32,22,56,-46),(-32,30,-75,77),(-32,-54,56,30)。

    输入

    第一行包括一个整数 T,表示测试数据组数
    然后每组数据之间都以一个空行
    每组数据中,每一行表示一个元素集合(以空行结束一个集合)
    数据保证每组数据中每个元素集合数量相同

    输出

    对于每组数据,一个整数表示一共有多少种选法,以空行结束一组数据

    输入示例

    1

    6
    -45 22 45 -16
    -41 -27 56 30
    -36 53 -37 77
    -36 30 -75 -46
    26 -38 -10 62
    -32 -54 -6 45

    输出示例

    5

    其他说明

    试题来源:UVA1152

    ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    讲解:

    因为n<=4000,所以得从四重循环得优化,我们只需要将a,b,c,d排序去重,将a,b中所有组合存下来放入c,d的所有组合中二分查找。

    代码实现:

    #include<iostream>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    using namespace std; 
    const int xx=2010;
    int a[xx],b[xx],c[xx],d[xx],sum1[xx*xx],sum2[xx*xx],n,dex1,dex2,ans;
    bool ff(int l,int r,int s)//二分查找(略) 
    {
        int i,j,mid;
        while(l<r)
        {
            mid=(l+r)/2;
            if(sum2[mid]==s) return true;
            else if(sum2[mid]>s) r=mid;
            else l=mid+1;
        }
        return false;
    }
    int main()
    { 
        int i,j,t;
        scanf("%d",&t);
        while(t!=0)
        {
            ans=0;
            dex1=0;
            dex2=0; 
            t--;
            scanf("%d",&n);
            for(i=0;i<n;i++) scanf("%d%d%d%d",&a[i],&b[i],&c[i],&d[i]);
            sort(a,a+n); //排序,便于去重
            sort(b,b+n);
            sort(c,c+n);
            sort(d,d+n);
            for(i=0;i<n;i++) 
            {
                if(i!=0 && a[i]==a[i-1]) continue; //去重 
                for(j=0;j<n;j++) 
                {
                    if(j!=0 && b[j]==b[j-1]) continue;//去重 
                    sum1[dex1++]=a[i]+b[j];//将a+b的值存进sum里 
                }
            }
            sort(sum1,sum1+dex1);//sum排序 
            for(i=0;i<n;i++)
            {
                if(i!=0 && c[i]==c[i-1]) continue;//去重 
                for(j=0;j<n;j++)
                {
                    if(j!=0 && d[j]==d[j-1]) continue;//去重 
                    sum2[dex2++]=c[i]+d[j];
                }
            }
            sort(sum2,sum2+dex2);
            for(i=0;i<dex1;i++) if(ff(0,dex2,-sum1[i])) ans++;//把 -c[i]-d[j]的值在sum里二分查找 
            cout<<ans<<endl;
        }
        return 0;
    }
    View Code

    如果内存超限(mle)我们可以牺牲时间:

    #include<iostream>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    using namespace std; 
    const int xx=4010;
    int a[xx],b[xx],c[xx],d[xx],sum[xx*xx],n,dex,ans;
    bool ff(int l,int r,int s)//二分查找(略) 
    {
        int i,j,mid;
        while(l<r)
        {
            mid=(l+r)/2;
            if(sum[mid]==s) return true;
            else if(sum[mid]>s) r=mid;
            else l=mid+1;
        }
        return false;
    }
    int main()
    { 
        int i,j,t;
        scanf("%d",&t);
        while(t!=0)
        {
            ans=0;
            dex=0;
            t--;
            scanf("%d",&n);
            for(i=0;i<n;i++) scanf("%d%d%d%d",&a[i],&b[i],&c[i],&d[i]);
            sort(a,a+n); //排序,便于去重
            sort(b,b+n);
            sort(c,c+n);
            sort(d,d+n);
            for(i=0;i<n;i++) 
            {
                if(i!=0 && a[i]==a[i-1]) continue; //去重 
                for(j=0;j<n;j++) 
                {
                    if(j!=0 && b[j]==b[j-1]) continue;//去重 
                    sum[dex++]=a[i]+b[j];//将a+b的值存进sum里 
                }
            }
            sort(sum,sum+dex);//sum排序 
            for(i=0;i<n;i++)
            {
                if(i!=0 && c[i]==c[i-1]) continue;//去重 
                for(j=0;j<n;j++)
                {
                    if(j!=0 && d[j]==d[j-1]) continue;//去重 
                    if(ff(0,dex,-c[i]-d[j])) ans++;//把 -c[i]-d[j]的值在sum里二分查找 
                }
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    apue学习笔记(第十五章 进程间通信)
    apue学习笔记(第十四章 高级I/O)
    apue学习笔记(第十三章 守护进程)
    各种仪器销售说明网站
    专业英语分类和查询
    c#网格控件,Excel控件
    sqlite支持linq
    使WebDev.WebServer.exe 当web服务器
    zip压缩文件测试
    c++爬虫子
  • 原文地址:https://www.cnblogs.com/lhc-yyl-lyx-lyh/p/8450105.html
Copyright © 2011-2022 走看看