CF Boring Partition

D. Boring Partition

其实这就是一道想法题,题意是:给出N个数和一个非负数H,将这N个数分成两个集合,可以有一个集合为空,给出一个计算公式f(i,j) = a[i] +a[j] (如果i != j && a[i] a[j] 在同一个集合),f(i,j) = a[i] +a[j] +h(i!=j && a[i] a[j] 不在同一个集合里),让你求出一种分法使得f(i,j)中的最大值与最小值的差值最小。

解题过程:刚开始想的是用两个优先队列,然后从头开始遍历,每次只要和队列中的最大值最小值进行计算就行了,这样一遍就可以找出最值,但是纠结的是不知道初始化怎么办,MAX_F,MIN_F怎么设,将前两个的差值设为最大值和最小值肯定不对,后来看到标签上写的是用排序和贪心,想着排完序之后怎么办,果然这个方向是对的。

排完序后就可以看出,这个序列有两种情况,一种是所有数字都属于同一个集合,所以这种情况中,F的最大值为a[n]+a[n-1] , 最小值为a[1] +a[2] ,其余的任意两个数的和都在这两个数之间,可以求出一个差值ans1 ,另一种情况就是分成两个集合,这个比较难想点,但是想清楚了也是一种贪心,是如果a[n],a[n-1] 在一个集合里,那么他们两个个和可能最大,如果a[1] ,a[n] 不在一个集合中,那么如果h>a[n-1]-a[1]的话,a[n]+a[1] +h >a[n]+a[n-1] ,至于其他的数,只要在a[1] 和a[n-1] 之间的数都会大于a[n]+a[n-1] ,根据最优分发,它们都要分到a[n]那一个集合中,这样的话才不会产生更大的F,而这种情况下的最小F是,a[1] + a[2] + h , 或者是a[2]  + a[3] ,最后只要判断上面两种情况,哪种产生的差值最小就可以了。

参考代码:

View Code
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>
#include <stack>
#include <queue>
#include <math.h>
#define  N 100005
using namespace std ;

int d[N] , a[N] ;

int min( int x , int y )
{
    return x > y ? y : x ;
}

int max( int x , int y )
{
    return x > y ? x : y ;
}

int main()
{
    int n , h , f_min1 , f_min2 , i , flag ;

    while ( scanf ( "%d%d" , &n , &h ) != EOF )
    {
        for ( i = 1 ; i <= n ; i++ )
        {
            scanf ( "%d" , &d[i] );
            a[i] = d[i] ;
        }
        sort( a + 1 , a + n + 1 ) ;
        f_min1 = ( a[n] + a[n-1] ) - ( a[1] + a[2] ) ;
        f_min2 =  max( a[1] + a[n] + h , a[n] + a[n-1] ) - min( a[1] + a[2] + h , a[2] + a[3] ) ;
        if ( n == 2 || f_min1 <= f_min2 )
        {
            printf ( "%d\n" , f_min1 ) ;
            for ( i = 1 ; i <= n ; i++ )
            {
                if( i == 1 )
                printf ( "1" );
                else
                printf ( " 1" ) ;
            }
            printf ( "\n" ) ;
        }
        else
        {
            printf ( "%d\n" , f_min2 ) ;
            flag = 0 ;
            for ( i = 1 ; i <= n ; i++ )
            {
                if ( d[i] == a[1] && !flag )
                {
                    flag = 1 ;
                    printf ( "2" ) ;
                }
                else
                printf ( "1" ) ;
                if ( i != n )
                printf ( " " ) ;
            }
            printf ( "\n" ) ;
        }
    }
    return 0 ;
}
posted @ 2012-11-09 11:03  Misty_1  阅读(176)  评论(0编辑  收藏  举报