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 }

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值