洛谷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\n",ans); return 0; }