zoukankan      html  css  js  c++  java
  • 洛谷3933 Chtholly Nota Seniorious 二分答案+贪心

    题目链接

    题意

    给你一个N*M的矩阵 (N,M <=2000)  把他分成两部分 使两部分的极差较大的一个最小  求这个最小值。然后分矩阵的要求是:每个部分内部的方块之间,可以通过上下左右相互到达,而且每个内部的方块之间互相到达,最多允许拐一次弯(不能出现“凹”233)

    二分答案+贪心

    二分上界是矩阵max-min   

    判断的时候 由于 分开的矩阵在每一行肯定是连续的 所以就按顺序扫一遍 判断一下在哪里分开即可

    还有就是由于最大值最小值所在的位置不确定 ,我们需要旋转3次这个矩阵然后求最优答案

    代码 

    #include<bits/stdc++.h>
    #define MAXN 2017
    #define INF 0x7f7f7f7f
    using namespace std;
    int N,M,a[MAXN][MAXN],maxa,mina=INF,ans=INF;
    bool check(int tmp){
        int pos=1;
        for(int i=1;i<=N;i++)
        {
            for(int j=1;j<=M;j++)
                if(a[i][j]<maxa-tmp)
                    pos=max(j+1,pos);
            for(int j=1;j<=M;j++)
                if(a[i][j]>mina+tmp)
                    if(j<pos)return 0;
        }
        return 1;
    }
    int Solve(){
        int l=0,r=maxa-mina;
        while(l<r){
            int mid=l+r>>1;
            if(check(mid))r=mid;
            else l=mid+1; 
        } 
        return l;
    }
    void flip1(){
        for(int i=1;i<=N/2;i++)
            for(int j=1;j<=M;j++)
                swap(a[i][j],a[N-i+1][j]);
    } 
    void flip2(){
        for(int j=1;j<=M/2;j++)
            for(int i=1;i<=N;i++)
                swap(a[i][j],a[i][M-j+1]);
    }
    
    int main()
    {
        scanf("%d%d",&N,&M);
        for(int i=1;i<=N;i++)
            for(int j=1;j<=M;j++){
                scanf("%d",&a[i][j]);
                maxa=max(maxa,a[i][j]);mina=min(mina,a[i][j]);
            }
        flip2();
        ans=Solve();
        flip1();ans=min(ans,Solve());
        flip2();ans=min(ans,Solve());
        flip2();ans=min(ans,Solve());
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    Scala之eq,equals,==的区别
    Spark Streaming流计算特点及代码案例
    刷题50—水壶问题
    刷题49(力扣3道题)
    刷题48——最长回文串
    刷题47——矩形重叠
    刷题46——拼写单词
    刷题45(力扣两道题)
    刷题44——岛屿的最大面积
    刷题43——最长上升子序列
  • 原文地址:https://www.cnblogs.com/Elfish/p/7714458.html
Copyright © 2011-2022 走看看