• HDU 4334——Trouble——————【贪心&水题】


    Trouble

    Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 5388    Accepted Submission(s): 1494


    Problem Description
    Hassan is in trouble. His mathematics teacher has given him a very difficult problem called 5-sum. Please help him.
    The 5-sum problem is defined as follows: Given 5 sets S_1,...,S_5 of n integer numbers each, is there a_1 in S_1,...,a_5 in S_5 such that a_1+...+a_5=0?
     
    Input
    First line of input contains a single integer N (1≤N≤50). N test-cases follow. First line of each test-case contains a single integer n (1<=n<=200). 5 lines follow each containing n integer numbers in range [-10^15, 1 0^15]. I-th line denotes set S_i for 1<=i<=5.
     
    Output
    For each test-case output "Yes" (without quotes) if there are a_1 in S_1,...,a_5 in S_5 such that a_1+...+a_5=0, otherwise output "No".
     
    Sample Input
    2
    2
    1 -1
    1 -1
    1 -1
    1 -1
    1 -1
    3
    1 2 3
    -1 -2 -3
    4 5 6
    -1 3 2
    -4 -10 -1
     
    Sample Output
    No
    Yes
     
    题目大意:给你5行每行n个数,问你是否可以在每行中取出一个数,让a1+a2+a3+a4+a5=0。

    解题思路:开始写了搜索,但是一直超时。然而超时好像是必然的,没办法剪枝。其实可以将前1、2行合成一行a,将3、4行合成一行b,从小到大排序。枚举剩下的最后一行c,枚举a,逆序枚举b。贪心思想在如果b的当前值跟a和c的和小于0,那么可以直接让a的指针加一,如果大于0,可以让b的指针减一,如果逆序遍历完b或正序遍历完a以后还没找到,那么就继续枚举c。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long INT;
    INT Map[6][210];
    INT a[42000];
    INT b[42000];
    INT c[210];
    int main(){
        int t,n;
        scanf("%d",&t);
        while(t--){
            scanf("%d",&n);
            for(int i=1;i<=5;i++){
                for(int j=0;j<n;j++){
                    scanf("%lld",&Map[i][j]);
                }
            }
            int na=0,nb=0,nc=0;
            for(int i=0;i<n;i++){   
                for(int j=0;j<n;j++){
                    a[na++]=Map[1][i]+Map[2][j];//合并1、2行
                    b[nb++]=Map[3][i]+Map[4][j];//合并3、4行
                }
            }
            int nn=n*n;
            sort(a,a+nn);   //递增排序
            sort(b,b+nn);   //递增排序
            na=1,nb=1,nc=1;
            for(int i=1;i<nn;i++){  //去重
                if(a[i]!=a[i-1]){
                    a[na++]=a[i];
                }
            }
            for(int i=1;i<nn;i++){  //去重
                if(b[i]!=b[i-1]){
                    b[nb++]=b[i];
                }
            }
            c[0]=Map[5][0];
            for(int i=1;i<n;i++){   //去重
                if(Map[5][i]!=Map[5][i-1]){
                    c[nc++]=Map[5][i];
                }
            }
            int flag=0;
            for(int i=0;i<nc&&(!flag);i++){  //n的复杂度
                for(int j=0,k=nb-1;k>=0&&j<na; ){//n*n的复杂度
                    INT cc=c[i]+a[j]+b[k];
                    if(cc<0){       //降低复杂度。模拟跳出一层循环
                        j++;
                    }else if(cc==0){
                        flag=1;
                        break;
                    }else{
                        k--;
                    }
                }
            }
            if(flag){
                puts("Yes");
            }else {
                puts("No");
            }
        }
        return 0;
    }
    

      

  • 相关阅读:
    Angular——事件指令
    Angular——数据绑定
    Angular——自定义指令
    Angular——表单指令
    Angular——引入模板指令
    Angular——内置指令
    Angular——基本使用
    Canvas——基本入门
    JS高级——面向对象方式解决tab栏切换问题
    JS高级——面向对象方式解决歌曲管理问题
  • 原文地址:https://www.cnblogs.com/chengsheng/p/4758368.html
Copyright © 2020-2023  润新知