码迷,mamicode.com
首页 > 其他好文 > 详细

51nod 1090 3个数和为0 & 51nod 1267 4个数和为0(标记二分)

时间:2014-11-30 23:24:34      阅读:328      评论:0      收藏:0      [点我收藏+]

标签:51nod   排序   

题目意思:

3个数的和为0:

http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1090

给出一个长度为N的无序数组,数组中的元素为整数,有正有负包括0,并互不相等。从中找出所有和 = 0的3个数的组合。如果没有这样的组合,输出No Solution。如果有多个,按照3个数中最小的数从小到大排序,如果最小的数相等则按照第二小的数排序。

Input
第1行,1个数N,N为数组的长度(0 <= N <= 1000)
第2 - N + 1行:A[i](-10^9 <= A[i] <= 10^9)
Output
如果没有符合条件的组合,输出No Solution。
如果有多个,按照3个数中最小的数从小到大排序,如果最小的数相等则继续按照第二小的数排序。每行3个数,中间用空格分隔,并且这3个数按照从小到大的顺序排列。
Input 示例
7
-3
-2
-1
0
1
2
3
Output 示例
-3 0 3
-3 1 2
-2 -1 3
-2 0 2
-1 0 1

题目分析:

此题可以二分,首先计算任意两个数的和存到数组b中,进行排序a(原数组)和b数组,进行判断a[i=0]+b[j=(n*(n-1))]=0?,如果三个数两两不等且等于0,则存到结果数组,(保证输出时结果不重复),最后输出结果集。详见代码,写的有点乱,望见谅!


AC代码:

<span style="font-size:18px;">#include<iostream>
#include<algorithm>
#include<cmath>
#define MAX 1001
using namespace std;
int a[MAX],b[3];
struct node{
    int si,sj;
}s[MAX*(MAX-1)];

struct Snode{
    int si,sj,sk;
}p[MAX*(MAX+5)];

int cmp1(node a,node b){
    if(a.si+a.sj<=b.si+b.sj) return 1;
    return 0;
}

int cmp2(Snode a,Snode b){
    if(a.si<b.si) return 1;
    else if(a.si==b.si&&a.sj<b.sj) return 1;
    else if(a.si==b.si&&a.sj==b.sj&&a.sk<b.sk) return 1;
    return 0;
}

int main()
{
    int n;
    while(cin>>n){
        int k=0;
        for(int i=0;i<n;i++){
            cin>>a[i];
            for(int j=0;j<i;j++){
                s[k].si=a[i];
                s[k++].sj=a[j];
            }
        }
        sort(a,a+n);
        sort(s,s+k,cmp1);
        int i=0,j=k-1,ok=1,kk=0;
        while(i<n&&j>=0){
            if(s[j].si+s[j].sj+a[i]==0){
                if(a[i]!=s[j].si&&a[i]!=s[j].sj){
                    ok=0;
                    b[0]=a[i]; b[1]=s[j].si; b[2]=s[j].sj;
                    sort(b,b+3);
                    p[kk].si=b[0];
                    p[kk].sj=b[1];
                    p[kk++].sk=b[2];
                }
                j--;
            }
            else if(s[j].si+s[j].sj+a[i]<0){
                i++;
            }
            else if(s[j].si+s[j].sj+a[i]>0){
                j--;
            }
        }
        //cout<<kk<<endl;
        sort(p,p+kk,cmp2);
        if(ok) cout<<"No Solution"<<endl;
        else{
            cout<<p[0].si<<" "<<p[0].sj<<" "<<p[0].sk<<endl;
            for(i=1;i<kk;i++){
                if(p[i].si==p[i-1].si&&p[i].sj==p[i-1].sj&&p[i].sk==p[i-1].sk) continue;
                else cout<<p[i].si<<" "<<p[i].sj<<" "<<p[i].sk<<endl;
            }
        }
    }
    return 0;
}</span>

四个数的和是否为0

http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1267


给出N个整数,你来判断一下是否能够选出4个数,他们的和为0,可以则输出"Yes",否则输出"No"。
Input
第1行,1个数N,N为数组的长度(4 <= N <= 1000)
第2 - N + 1行:A[i](-10^9 <= A[i] <= 10^9)
Output
如果可以选出4个数,使得他们的和为0,则输出"Yes",否则输出"No"。
Input 示例
5
-1
1
-5
2
4
Output 示例
Yes

题目分析:
本题和三个数的和为0,算法一样,只是这里数组b和自己求和是否为0,比较是否用两两相等的时候,需要比较下标,只要相加是将两个数的下标对应存起来即可。


AC代码:

<span style="font-size:18px;">/**
 *序列中可能有重复的数
 *首先两个数相加为一个序列,再用这个序列和和本序列相加是否等于0
 *判断是注意比较是否四个数是否相等,由于可能有重复的数,只能用
 *位置判断,及记录两个数的位置下标进行比较,
 *记过等于0且不相等YES,否则NO
 */
#include<iostream>
#include<algorithm>
#include<cmath>
#define MAX 1001
using namespace std;
int a[MAX];
struct node{
    int i,j;
    int sum;
}s[MAX*(MAX-1)];

int cmp1(node a,node b){
    if(a.sum<=b.sum) return 1;
    return 0;
}

int main()
{
    int n;
    while(cin>>n){
        int k=0;
        for(int i=0;i<n;i++){
            cin>>a[i];
            for(int j=0;j<i;j++){//合为两个数的和
                s[k].i=i;
                s[k].j=j;
                s[k++].sum=a[i]+a[j];
            }
        }
        sort(s,s+k,cmp1);
        int i=0,j=k-1,ok=1;
        while(i<=j){
            if(s[i].sum+s[j].sum==0){
                if(s[i].i!=s[j].i&&s[i].i!=s[j].j&&s[i].j!=s[j].i&&s[i].j!=s[j].j){//四个下标任意不相等
                    ok=0;
                    break;
                }
                i++; j--;
            }
            else if(s[i].sum+s[j].sum<0){
                i++;
            }
            else if(s[i].sum+s[j].sum>0){
                j--;
            }
        }
        if(ok) cout<<"No"<<endl;
        else cout<<"Yes"<<endl;
    }
    return 0;
}</span>


51nod 1090 3个数和为0 & 51nod 1267 4个数和为0(标记二分)

标签:51nod   排序   

原文地址:http://blog.csdn.net/fool_ran/article/details/41629081

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!