UVa 1614 - Hell on the Markets(贪心)

贪心部分的理论依据:前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。所以一定可以凑出a[k+1]-p。所以只需从之前凑出sum[k]里面剪掉凑出a[k+1]-p的数就可以凑出sum[k]+p。所以从1~sum[k+1]都可以凑出。


输入n个数,第i个数ai满足1≤ai≤i。对每个数添加符号,使和值为0。

排序后从最大的数开始贪心就好。这次用了一些c++不常用的特性写的,一开始缺了个头文件CE了。

#include<iostream>
#include<algorithm>
#include<iterator>
using namespace std;
const int maxn=100010;
struct q{
    int num,id;
    friend ostream& operator << (ostream &out,const q& x){
        cout<<x.num;
        return out;
    }
};
q a[maxn];
int main(){
    int n;
    while(cin>>n){
        long long sum=0;
        for(int i=0;i<n;++i){
            a[i].id=i;
            cin>>a[i].num;
            sum+=a[i].num;
        }
        if(sum&1) {cout<<"No\n";continue;}
        sum>>=1;
        sort(a,a+n,[](q& a,q& b){return a.num>b.num;});
        for(int i=0;i<n;++i){
            if(a[i].num<=sum){
                sum-=a[i].num;
                a[i].num=1;
            }
            else a[i].num=-1;
        }
        sort(a,a+n,[](q& a,q& b){return a.id<b.id;});
        cout<<"Yes\n";
        copy(a,a+n,ostream_iterator<q>(cout," "));
        cout<<endl;
    }
    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值