zoukankan      html  css  js  c++  java
  • hdu 1270

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1270

    思路:我们知道排序后sum[1]==num[1]+num[2];sum[2]==num[1]+num[3];但是num[2]+num[3]的值是不确定的,因此我们需要i(3,m)枚举,然后求出num[3]之后,将

    num[1]+num[2],num[1]+num[3],num[2]+num[3]的值标记,对于要求的num[4],在sum[]中的一个没有被标记过的一定是num[1]+num[4]的值,求出num[4]之后,在对num[1]+num[4],num[2]+num[4]....进行标记(如果都已标记,说明不成立,退出,再次枚举num[2]+num[3]);此后就可以依此求出num[5]...num[n]...如果最后成功,那么直接退出最外层循环,输出num[1]~num[n];

    View Code
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<cmath>
     5 #include<algorithm>
     6 using namespace std;
     7 const int MAXN=110;
     8 bool mark[MAXN*MAXN];
     9 int sum[MAXN*MAXN];
    10 int num[MAXN];
    11 /*
    12 设所求的n个数按从小到大排列为a1,a2....an。
    13 a1+a2一定是n*(n-1)/2个数的序列中最小的,a1+a3一定是次小的,通过枚举a2+a3的值解出符合条件的a1,a2,a3,
    14 把他们两两相加的结果从n*(n-1)/2个数中排除,然后n*(n-1)/2个数中剩下的第一个没有被排除的数一定是a1+a4的值,
    15 这样可以求的a4,然后再从n*(n-1)/2个数中除去a1+a4,a2+a4,a3+a4,然后n*(n-1)/2个数中剩下的第一个没有被排除
    16 的数一定是a1+a5的值,这样可以求的a5,如此重复,直到求的an的值,并除去a1+an,a2+an,....an-1+an,此时如果n*(n-1)/2
    17 个数已经全部除去,那么就得到了答案,否则,说明枚举的a2+a3的值仍不合要求,继续枚举下一个a2+a3的值。
    18 */
    19 
    20 
    21 int main(){
    22     int n;
    23     while(~scanf("%d",&n)&&n){
    24         int m=n*(n-1)/2;
    25         memset(sum,0,sizeof(sum));
    26         memset(num,0,sizeof(num));
    27         for(int i=1;i<=m;i++)scanf("%d",&sum[i]);
    28         sort(sum+1,sum+m+1);
    29         for(int i=3;i<=m;i++){
    30             //枚举求出num[1],num[2],num[3];
    31             //num[1]+num[2]一定为sum[1];
    32             //num[1]+num[3]一定为sum[2];
    33             //而num[2]+num[3]的值不确定,因此枚举i(3,m);
    34             num[2]=(sum[1]-sum[2]+sum[i])/2;
    35             num[1]=sum[1]-num[2];
    36             num[3]=sum[2]-num[1];
    37             if(num[2]+num[3]!=sum[i])continue;
    38 
    39             memset(mark,false,sizeof(mark));
    40             mark[i]=true;
    41             int k=3;//从第三个开始排除
    42             bool flag=true;
    43             for(int j=4;j<=n&&flag;j++){
    44                 while(mark[k])k++;
    45                 num[j]=sum[k]-num[1];
    46                 mark[k]=true;
    47                 //去掉num[2]+num[j],num[3]+num[j],num[4]+num[j]....num[j-1]+num[j];
    48                 //那么剩下的第一个没有被排除的数一定是num[1]+num[j+1](此时是下一个循环)
    49                 for(int l=2;l<j&&flag;l++){
    50                     //排除num[j]+num[l](2<=l<=j-1)
    51                     for(int x=k+1;x<=m;x++){
    52                         flag=false;
    53                         if(!mark[x]&&num[l]+num[j]==sum[x]){
    54                             mark[x]=true;
    55                             flag=true;
    56                             break;
    57                         }
    58                     }
    59                 }
    60             }
    61             if(flag)break;//说明此时已经生出n个数
    62         }
    63         for(int i=1;i<n;i++){
    64             printf("%d ",num[i]);
    65         }
    66         printf("%d\n",num[n]);
    67     }
    68     return 0;
    69 }
  • 相关阅读:
    STL的适配器、仿函数学习之一:accumulate和for_each的使用心得
    百度笔试题--------数字拼接,求出最小的那个
    百度面试题----依概率生成
    百度笔试题----C语言版revert
    百度笔度题-----蚂蚁爬杆问题
    Try....Catch......Finally 的执行顺序
    数据库SQL SERVER 2008R2 远程连接配置说明
    C#中的数据库的连接方式分类说明(转载)
    网络通信—udp使用领悟
    (转载)C#网络通信之TCP连接
  • 原文地址:https://www.cnblogs.com/wally/p/3051382.html
Copyright © 2011-2022 走看看