zoukankan      html  css  js  c++  java
  • 2259: matrix

    2259: matrix

    时间限制: 1 Sec  内存限制: 256 MB
    提交: 185  解决: 34
    [提交][状态][讨论版][命题人:admin]

    题目描述

    在麦克雷的面前有N个数,以及一个R*C的矩阵。现在他的任务是从N个数中取出 R*C 个,并填入这个矩阵中。矩阵每一行的法值为本行最大值与最小值的差,而整个矩阵的法值为每一行的法值的最大值。现在,麦克雷想知道矩阵的最小法值是多少。

    输入

    输入共两行。

    第一行是三个整数:n,r,c。(r, c <= 104, r * c <= n <= 106

    第二行是 n 个整数 Pi。(0 < pi <= 109)

    输出

    输出一个整数,即满足条件的最小的法值。

    样例输入

    7 2 3
    170 205 225 190 260 225 160
    

    样例输出

    30
    /*
    解法
    
    考虑矩阵中的两行a和b,a1<a2<...<aC
    ,b1<b2<...<bC,如果aC>b1
    
    ,那么交换aC和b1可以得到更优的答案。
    所以每一行的值域是不会有交集的。
    
    将所有数升序排序。
    设已知答案为ans;
    顺序枚举每一个数,如果a[i+C−1]−a[i]<=ans
    
    ,我们就可以贪心地把这C个数放进矩阵,枚举完后判断一下是否能够凑齐R行。
    证明:
    设选取a[i+k]..a[i+k+C-1]会比选取a[i]..a[i+C-1]更优。
    设f(x)为[x..n]的最大答案。
    那么选取a[i+k]..a[i+k+C-1]能够得到的最大答案即为f(i+k+C)+1;
    选取a[i+k]..a[i+C-1]能够得到的最大答案即为f(i+C)+1;
    显然f(x)是减函数。
    所以与假设违背。
    
    二分答案ans。
    就可以将原问题转化为上述问题。
    
    
    */
    
    
    #include<iostream>
    #include<algorithm>
    
    using namespace std ;
    
    #define maxn 1100000
    int n , r , c ; 
    int num[maxn] ; 
    
    bool check(int max_ans){
        int cnt = 0 ;
        for(int i=c ; i<=n ; i++){
            if(num[i] - num[i-c+1] <= max_ans){
                cnt++ ;
                i = i + c-1 ; //后续的 i++ 会修正i值
                if(cnt>=r){
                    return true ; 
                }
            }
        }
        return false ; 
    }/*
    bool check(int limit){
        
        int cnt=0;
        for (int i=1;i<=n-c+1;i++){
            if (num[i+c-1]-num[i]<=limit){
                cnt++;
                i=i+c-1;
                if (cnt>=r) return true;
            }
        }
        return false;
    }
    */
    int main(){
        int  right =0; 
        cin>>n>>r>>c ; 
        for(int i=1 ; i<=n ; i++)
            cin>>num[i] , right = max(right,num[i]);
    
        sort(num+1 , num+1+n) ; 
    
        int left = 0 ;//, right = 1000000001 ; 
        int mid ; 
        while(left<right){
            mid = (left+right)/2 ; 
            if(check(mid)){
                right = mid ; 
            }else{
                left = mid+1 ; 
            }
        }
    
        cout<<left<<endl ; 
        return 0 ; 
    } 


  • 相关阅读:
    docker~save与load的使用
    docker~从Dockerfile到Container的过程(终于算是OK了)
    docker~使用阿里加速器
    Draw2d中的布局管理器Layout比较
    利用glibc中锁结构的信息解决死锁问题
    android 利用重力感应监听 来电时翻转手机后静音。
    hdu 1754 I Hate It
    九度笔记之 1209最小邮票数
    java zip工具类
    基于XMPP实现的Openfire的配置安装+Android客户端的实现
  • 原文地址:https://www.cnblogs.com/yi-ye-zhi-qiu/p/8905129.html
Copyright © 2011-2022 走看看