zoukankan      html  css  js  c++  java
  • 【uva 1614】Hell on the Markets(算法效率--贪心)

    题意:有一个长度为N的序列A,满足1≤Ai≤i,每个数的正负号不知。请输出一种正负号的情况,使得所有数的和为0。(N≤100000)

    解法:(我本来只想静静地继续做一个口胡选手...←_← 但是因为这题的贪心实在是太厉害了!我就单看,就盯了题解半小时以上...而代码又那么短,我就打了代码了...其实我又不太理解为什么一定要排序。)

    贪心部分的理论依据:前i个数可以凑出1~sum[i]的所有整数。

    证明:第二类数学归纳,n=1时成立,假设n=k之前所有项都成立,当n=k+1时。sum[k+1]=sum[k]+a[k+1]。
    只需证明能凑出sum[k]+1~sum[k+1]间的整数即可。设1≤p≤a[k+1],sum[k]+p=sum[k]+a[k+1]-(a[k+1]-p)。
    因为1≤a[i]≤i,易得sum[k]≥k,a[k+1]-p≤k。又因为已知前k个数可以凑出1~sum[k],所以一定可以凑出a[k+1]-p。
    所以只需从之前凑出sum[k]里面剪掉凑出a[k+1]-p的数就可以凑出sum[k]+p。所以从1~sum[k+1]都可以凑出。

    实现就是输入时存一下sum,若为奇数就无解,否则再排个序,从大到小扫一遍,选凑成和为sum/2的数的符号为+,其余为-。

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<algorithm>
     4 #include<iostream>
     5 using namespace std;
     6 
     7 const int N=100010;
     8 struct node{int x,id;}a[N];
     9 int b[N],ans[N];
    10 
    11 bool cmp(node x,node y) {return x.x>y.x;}
    12 int main()
    13 {
    14     int n;
    15     long long sum;//不能用int
    16     while (~scanf("%d",&n))
    17     {
    18       sum=0;
    19       for (int i=1;i<=n;i++)
    20       {
    21         scanf("%d",&a[i].x);
    22         a[i].id=i, sum+=a[i].x;
    23       }
    24       if (sum%2) {printf("No
    ");continue;}
    25       printf("Yes
    ");
    26       sum/=2;
    27       sort(a+1,a+1+n,cmp);
    28       for (int i=1;i<=n;i++)
    29       {
    30         if (a[i].x<=sum) ans[a[i].id]=1,sum-=a[i].x;
    31         else ans[a[i].id]=-1;
    32       }
    33       printf("%d",ans[1]);
    34       for (int i=2;i<=n;i++)
    35         printf(" %d",ans[i]);
    36       printf("
    ");
    37     }
    38     return 0;
    39 }
  • 相关阅读:
    关于SUID、SGID、Sticky(转载)
    对Linux下TCP连接相关配置的优化记录(转载)
    ACL权限设置(转载)
    如何把一个命令加入到某个用户sudo的列表中(转载)
    菜鸟的逆袭 目标
    菜鸟的逆袭 自我介绍
    Weekly Work from表单练习
    CSS属性display的值及其描述
    CSS Position
    电源防反接保护电路
  • 原文地址:https://www.cnblogs.com/konjak/p/6052536.html
Copyright © 2011-2022 走看看