【2018/10/02】T2 - 二分 -矩阵分组

矩阵分组 
【描述】 
  有 N 行 M 列的矩阵,每个格子中有一个数字,现在需要你将格子的数字分为 A,B两部分 
要求: 
1、每个数字恰好属于两部分的其中一个部分 
2、每个部分内部方块之间,可以上下左右相互到达,且每个内部方块之间可以相互到达,
且最多拐一次弯 
 
如: 
AAAAA   AAAAA   AAAAA 
AABAA   BaAAA   AAABB 
ABBBA   BBAAA   AAABB 
AABAA   BaAAA   ABBBB 
AAAAA   AAAAA   BBBBB 
 
     (1)                   (2)                  (3)   
其中(1)(2)是不允许的分法,(3)是允许的分法。在(2)中,a属于 A区域,这两个 a元素之间互相到达,但是不满足只拐一次弯到达。 
  
问:对于所有合法的分组中,A 区域和 B 区域的极差,其中极差较大的一个区域最小值是多少 
 提示:极差就是区域内最大值减去最小值。 
【输入】 
第一行两个正整数 n,m  
接下来n 行,每行 m个自然数A_{i,j}表示权值 
【输出】 
输出一行表示答案 
【输入样例】 
4 4 
1 12 6 11 
11 4 2 14 
10 1 9 20 
4 17 13 10 
【输出样例】 
11 
 
【样例解释】 
1  12 6        11 
11 4  2        14 
10 1  9        20 
4        17 13 10 
 
分法不唯一,如图是一种合法的分法。左边部分极差 12-1=11,右边一块极差 20-10=10,
所以答案取这两个中较大者 11。没有别的分法,可以使答案更小。 
【测试数据】 
测试点  N,m范围 
1,2  n<=10,m<=10 
3-4  n=1,m<=2000 
5-7  n<=200,m<=200 
8-10  n<=2000,m<=2000 
所有权值1<=a_ij<=10^9 

 

分析

首先面对这种最大最小的问题,就应该思考一下二分答案,而这道题恰好也就用到了

接着分析一下题目中的分法要求,发现最后只会存在乘阶梯状下降或上升的部分(因为只能拐一次弯)

然后我们二分极差,重点就在于check函数了

如何来check呢?这是一个值得思考的问题,显然,一个部分不可能既包含整个矩阵的最大值又包含矩阵的最小值,这样肯定不是最优的情况,那么我们就可以依据这一点来进行check。

由于分出来的每个区域必定会占一个角,

如果我们从最大值所在的区域来看的话

可能会分别在不同的角上

而在不同的角判断的方法不一样

因为写好几种判断太麻烦了

所以直接存把矩阵旋转90.180.270度的情况一起存下来

相当于默认角在某一个位置,这样就可以用一种判断的方法就可以把所有情况都判断完了

不过存储的写法很是巧妙啊,详细见代码

简直想去结交一下这篇代码的原码主

 

代码

#include<bits/stdc++.h>
#define P 19260817
#define ll long long
#define in read()
#define N 2009
using namespace  std;
inline int read(){
	char ch;int res=0;
	while((ch=getchar())<'0'||ch>'9');
	while(ch>='0'&&ch<='9'){
		res=(res<<3)+(res<<1)+ch-'0';
		ch=getchar();
	}
	return res;
}
int n,m,a[4][N][N],maxn=-1,minn=1000000009;
int end[N];
bool C(int u,int d){
	if(u&1) swap(n,m);//由于旋转后行列会发生变化,我们就要顺带把n,m换一下
	end[0]=m;
	int i,j;
	for(i=1;i<=n;++i){
		for(j=1;j<=end[i-1];++j)
		{
			if(maxn-a[u][i][j]>d) break;
		}
		end[i]=j-1;
	}//构造完包含最大值的区域,下面开始验证包含最小值的区域是否满足极差在d以内
	for(int i=1;i<=n;++i){
		for(int j=end[i]+1;j<=m;++j){
			if(a[u][i][j]-minn>d){
				if(u&1) swap(n,m);//还要换回来
				return false;
			}
		}
	}
	if(u&1) swap(n,m);
	return true;
}
bool check(int mid){
	if(C(0,mid)) return true;//四个角落分别搞一遍
	if(C(1,mid)) return true;
	if(C(2,mid)) return true;
	if(C(3,mid)) return true;
	return false;
}
int main(){
	n=in;m=in;int t;
	int x=1,x1=1,x2=n,x3=m,y=1,y1=n,y2=m,y3=1;
	for(int i=1;i<=n;++i){
		for(int j=1;j<=m;++j){
			t=a[0][x][y++]=a[1][x1++][y1]=a[2][x2][y2--]=a[3][x3--][y3]=in;//旋转后存储,这个东西,自己画下图,或者举几个例子就明白了
			if(t>maxn) maxn=t;
			if(t<minn) minn=t;
		}
		x++;y=1;
		x1=1;y1--;
		x2--;y2=m;
		x3=m;y3++;
	}
	int l=0,r=maxn-minn,ans;
	while(l<=r){//二分
		int mid=l+r>>1;
		if(check(mid)) ans=mid,r=mid-1;
		else l=mid+1;
	}
	printf("%d",ans);
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
sudo make install Making install in libfcgi make[1]: Entering directory '/home/yk/fcgi-2.4.1-SNAP-0910052249/libfcgi' make[2]: Entering directory '/home/yk/fcgi-2.4.1-SNAP-0910052249/libfcgi' test -z "/home/yk/fcgi/lib" || mkdir -p -- "/home/yk/fcgi/lib" /bin/bash ../libtool --mode=install /usr/bin/install -c 'libfcgi.la' '/home/yk/fcgi/lib/libfcgi.la' /usr/bin/install -c .libs/libfcgi.so.0.0.0 /home/yk/fcgi/lib/libfcgi.so.0.0.0 (cd /home/yk/fcgi/lib && { ln -s -f libfcgi.so.0.0.0 libfcgi.so.0 || { rm -f libfcgi.so.0 && ln -s libfcgi.so.0.0.0 libfcgi.so.0; }; }) (cd /home/yk/fcgi/lib && { ln -s -f libfcgi.so.0.0.0 libfcgi.so || { rm -f libfcgi.so && ln -s libfcgi.so.0.0.0 libfcgi.so; }; }) /usr/bin/install -c .libs/libfcgi.lai /home/yk/fcgi/lib/libfcgi.la /usr/bin/install -c .libs/libfcgi.a /home/yk/fcgi/lib/libfcgi.a chmod 644 /home/yk/fcgi/lib/libfcgi.a arm-xilinx-linux-gnueabi-ranlib /home/yk/fcgi/lib/libfcgi.a ../libtool: line 6556: arm-xilinx-linux-gnueabi-ranlib: command not found /bin/bash ../libtool --mode=install /usr/bin/install -c 'libfcgi++.la' '/home/yk/fcgi/lib/libfcgi++.la' libtool: install: warning: relinking `libfcgi++.la' (cd /home/yk/fcgi-2.4.1-SNAP-0910052249/libfcgi; /bin/bash ../libtool --tag=CXX --mode=relink arm-xilinx-linux-gnueabi-g++ -march=armv7-a -mthumb -mfpu=neon -mfloat-abi=hard -mcpu=cortex-a9 --sysroot=/home/yk/sdk/sysroots/cortexa9t2hf-neon-xilinx-linux-gnueabi -O2 -pipe -g -feliminate-unused-debug-types -Wl,-O1 -Wl,--hash-style=gnu -Wl,--as-needed -o libfcgi++.la -lfcgi -rpath /home/yk/fcgi/lib fcgio.lo ) arm-xilinx-linux-gnueabi-g++ -march=armv7-a -mthumb -mfpu=neon -mfloat-abi=hard -mcpu=cortex-a9 --sysroot=/home/yk/sdk/sysroots/cortexa9t2hf-neon-xilinx-linux-gnueabi -shared -nostdlib /home/yk/sdk/sysroots/cortexa9t2hf-neon-xilinx-linux-gnueabi/usr/lib/crti.o /home/yk/sdk/sysroots/cortexa9t2hf-neon-xilinx-linux-gnueabi/usr/lib/arm-xilinx-linux-gnueabi/8.2.0/crtbeginS.o .libs/fcgio.o -Wl,--rpath -Wl,/home/yk/fcgi/lib -L/home/yk/fcgi/lib -lfcgi -L/home/yk/sdk/sysroots/x86_64-petalinux-linux/usr/lib/arm-xilinx-linux-gnueabi/gcc/arm-xilinx-linux-gnueabi/8.2.0 -L/home/yk/sdk/sysroots/cortexa9t2hf-neon-xilinx-linux-gnueabi/lib -L/home/yk/sdk/sysroots/cortexa9t2hf-neon-xilinx-linux-gnueabi/usr/lib/arm-xilinx-linux-gnueabi/8.2.0 -L/home/yk/sdk/sysroots/cortexa9t2hf-neon-xilinx-linux-gnueabi/usr/lib -lstdc++ -lm -lc -lgcc_s /home/yk/sdk/sysroots/cortexa9t2hf-neon-xilinx-linux-gnueabi/usr/lib/arm-xilinx-linux-gnueabi/8.2.0/crtendS.o /home/yk/sdk/sysroots/cortexa9t2hf-neon-xilinx-linux-gnueabi/usr/lib/crtn.o -march=armv7-a -mthumb -mfpu=neon -mfloat-abi=hard -mcpu=cortex-a9 -Wl,-O1 -Wl,--hash-style=gnu -Wl,--as-needed -Wl,-soname -Wl,libfcgi++.so.0 -o .libs/libfcgi++.so.0.0.0 ../libtool: line 4501: arm-xilinx-linux-gnueabi-g++: command not found libtool: install: error: relink `libfcgi++.la' with the above command before installing it Makefile:256: recipe for target 'install-libLTLIBRARIES' failed make[2]: *** [install-libLTLIBRARIES] Error 1 make[2]: Leaving directory '/home/yk/fcgi-2.4.1-SNAP-0910052249/libfcgi' Makefile:459: recipe for target 'install-am' failed make[1]: *** [install-am] Error 2 make[1]: Leaving directory '/home/yk/fcgi-2.4.1-SNAP-0910052249/libfcgi' Makefile:373: recipe for target 'install-recursive' failed make: *** [install-recursive] Error 1
最新发布
07-21
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值