版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/huangjingyuan107/article/details/83574621
题目
一个
的矩阵,分为A和B两个部分,其中AB两个部分都要连通,且不能凹。
如何分AB部分,才能使得最后A,B部分的极差最大值最小?
输出这个最小值。
题解
原题出处:JOI2016 The Kingdom of JOIOI
抓住题目的关键点。假设最大值在A块,最小值在B块。
如果二分出答案mid之后,则A块的值域为
,B块的值域为
又AB两块都不凹,所以,分割线必然是从右上到坐下。分界线不会递增。
比赛的时候被一个地方卡住了。
究竟哪一块是A块,哪一块是B块。
强制让左上角是A块,右下角是B块。然后变换一下图形。
旋转方法:(顺时针旋转90度)
for i=1 to n do
for j=1 to m do
b[j][n-i+1]=a[i][j];
memcpy(b,a,sizeof(b));
当然,这题不需要旋转,只需要翻转即可。
当然还有更优的
方法。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define N 2010
#define P(a) putchar(a)
#define Max(x,y) ((x)>(y)?(x):(y))
#define Min(x,y) ((x)<(y)?(x):(y))
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fd(i,a,b) for(i=a;i>=b;i--)
using namespace std;
int i,j,k,l,n,m,ans;
int a[N][N],b[N][N];
int wl,wr,wm,vw,vx,MX,MN;
int vl,vr,vm;
bool i1,i2;
int read(){
int fh=0,rs=0;char ch=0;
while((ch<'0'||ch>'9')&&(ch^'-'))ch=getchar();
if(ch=='-')fh=1,ch=getchar();
while(ch>='0'&&ch<='9')rs=(rs<<3)+(rs<<1)+(ch^'0'),ch=getchar();
return fh?-rs:rs;
}
void write(int x){
if(x>9)write(x/10);
P(x%10+'0');
}
bool check(int vm){
int i,j=m,k,l;
fo(i,1,n){
l=j;
fo(k,1,j){
if(MX-a[i][k]>vm){
l=k-1;
break;
}
}
fo(k,l+1,m)
if(a[i][k]-MN>vm){
return 0;
}
j=l;
}
return 1;
}
void doit(){
vl=0,vr=MX-MN;vx=vl;
while(vl<=vr){
vm=(vl+vr)>>1;
if(check(vm))vx=vm,vr=vm-1;else vl=vm+1;
}
ans=Min(ans,vx);
}
void fanzhuan0(){
int i,j;
fo(i,1,n)fo(j,1,m/2)swap(a[i][j],a[i][m-j+1]);
}
void fanzhuan1(){
int i,j;
fo(i,1,n/2)fo(j,1,m)swap(a[i][j],a[n-i+1][j]);
}
int main(){
n=read();m=read();
MX=0,MN=2147483647;
fo(i,1,n)fo(j,1,m){
a[i][j]=read();
MX=Max(MX,a[i][j]);
MN=Min(MN,a[i][j]);
}
ans=2147483647;
doit();fanzhuan0();
doit();fanzhuan1();
doit();fanzhuan0();
doit();
printf("%d",ans);
return 0;
}~