uva 1614Hell on the Markets

来源:互联网 发布:域名一般多少钱 编辑:程序博客网 时间:2024/06/03 19:26

题目大意:给定n个数字序列,1<= ai <= i ;问如何确定次序列每个数的正负号,使得其和为0.

首先应该知道:如想满足题意,则原序列的和为偶数。

第二就是如何解读题中给定的元素的不等式。

我也是看了别人的报告才知道的。 就是1---sum[i]的每个数都可以使用这个序列的全部后者部分数的和组合而成。

使用数学归纳法可以证明。

这样我们就可以从n-1开始逆序的查找是否可以组合成sum/2即t.

算法是如果当前值大于t,则看下一个数,如果当前值小于t,t-当前值。。。。由上面的结论是这样最后肯定是能使得t=0的。

////  main.cpp//  uva 1614 - Hell on the Markets////  Created by XD on 15/8/17.//  Copyright (c) 2015年 XD. All rights reserved.//#include <iostream>#include <string>#include <queue>#include <stack>#include <stdio.h>#include <stdlib.h>#include <math.h>#include<vector>#include <string.h>#include <string>#include <algorithm>#include <set>#include <map>#include <cstdio>#define ll long longusing namespace std ;const int maxn = 100000+ 5 ;int ans[maxn] ;int n ;struct num{    int pos , key ;    bool operator < (const num &n ) const{        return  key < n.key ;    } ;};num  a[maxn] ;int vis[maxn] ;bool judge(ll sum){    memset(vis, 0,sizeof(int) * n +5) ;//    sort(a, a + n ) ;    int t = n -1 ;    while (sum >0) {        if (sum  -a[t].key >= 0 ) {            vis[a[t].pos]= 1 ;            sum -= a[t].key ;        }        t-- ;    }    return true  ;}int main(int argc, const char * argv[]) {    ll sum = 0 ;    while (scanf("%d",&n)==1 ) {        sum = 0 ;        for (int i = 0;i  < n ; i++) {            scanf("%d" ,&a[i].key) ;            a[i].pos = i ;            sum += a[i].key  ;        }        if (sum%2 == 1) {            printf("No\n") ;            continue ;        }        else{            ll mid = sum/2 ;            if (judge(mid)) {                printf("Yes\n") ;                printf("%d" , vis[0]==0?1:-1) ;                for (int i =1; i < n; i++) {                    printf(" %d",vis[i]==0?1:-1) ;                }            }        }        printf("\n") ;            }    return 0;}


0 0