UVA1614 - Hell on the Markets

*这道题主要是先证明对任意sum[i]都可以由a1…ai的部分和表示出或者全部。
证明:1.对于k == 1,sum[k]由a1表示出
2。假设对于任意k > 1成立,则sum[k]可有a1…ak中的数字之和表示出。那么sum[k+1] = sum[k] + a[k+1];设1<= p <= a[k+1], 那么sum[k] + p = sum[k] + a[k+1] - (a[k+1] - p);
现在证明sum[k] - (a[k+1] - p)可有a1..ak中的数字之和表示出。因为sum[k] >= k,,并且a[k+1] - p 大于等于零,小于等于a[k+1] - 1,因为a[k+1] <= k+1, 所以0<= a[k+1] - p <= k; 所以0<=sum[k] - (a[k+1] - p) <= sum[k], 因为1..sum[k]中的数可有a1…a[k]部分数之和表示出,所以得证。*

#include <iostream>
#include <queue>
#include <cstdio>
#include <vector>
#include <algorithm>

using namespace std;

struct point{
    int num, s, pos;
}op[100005];
int cmp(const point &a, const point &b)
{
    return a.num < b.num;
}
int tmp(const point &a, const point &b)
{
    return a.pos < b.pos;
}
int main()
{
    int n;

    while(cin >> n)
    {
        long long sum = 0;
        for(int i = 0; i < n; i++)
        {
            int m;

            scanf("%d", &m);
            op[i].num = m;
            op[i].pos = i;
            op[i].s = 1;
            sum += m;

        }
        if(sum % 2){
            cout << "No" << endl;
            continue;
        }
        sort(op, op+n, cmp);
        sum /= 2;
        for(int i = n-1; i >= 0; i--)
        {
            if(sum >= op[i].num){
                sum -= op[i].num;
                op[i].s = -1;
            }
            if(sum == 0)
                break;
        }
        cout << "Yes" << endl;
        sort(op, op+n, tmp);
        for(int i = 0; i < n-1; i++)
            cout << op[i].s << " ";
        cout << op[n-1].s << endl;
    }

    return 0;
}

你可能感兴趣的:(UVA1614 - Hell on the Markets)