• 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 ;
    }
  • 相关阅读:
    Java中的String为什么是不可变的? -- String源码分析
    理解值和对象-快照图
    线程Thread
    Spring Cloud中,如何解决Feign/Ribbon第一次请求失败的问题?
    不要做一个浮躁的程序员
    关于在springboot中利用@Value注解读取配置文件中的属性值得问题
    Intellij Idea expired
    javascript事件之:谈谈自定义事件
    javascript事件之: 事件冒泡, 事件捕获 ,阻止默认事件
    windows7自带远程连接工具连接不上远程,只有windows服务器版本能连接tsmmc能连接的问题
  • 原文地址:https://www.cnblogs.com/misty1/p/2762226.html
Copyright © 2020-2023  润新知