JZOJ-senior-5938. 【NOIP2018模拟10.30】分离计划

7 篇文章 0 订阅
Time Limits: 2000 ms Memory Limits: 262144 KB

Description

众所周知,小Z拥有者足以毁灭世界的力量,可惜他不能控制这份力量,小J和小Z的关系十分亲密,一天小J预感到了小Z体内的力量将要爆发。

这次爆发的力量比以往都要强大,以至于将小Z分为了两个整体,彼此之间靠着万有引力互相靠近,一旦融合,世界将不复存在。

为了拯救世界,小J决定打造一个容器G,将小Z的两个部分分别装在容器G的一个部分,用以控制小Z

容器由n*m个魔法水晶组成,他们组成了一个n行m列的矩阵,每个魔法水晶都有自己的能量值,容器需要

被分为两个部分,使得每个魔法水晶都属于且仅属于一个部分,并且任何一个魔法水晶都可以在矩阵中只经过和自己属于同一部分的魔法水晶由一条最多改变一次方向的路径抵达另一个和他处于同一部分的魔法水晶

例如:
AAAAA. .AAAAA. .AAAAA
AABAA. .BAAAA. .AAABB
ABBBA. .BBAAA. .AAABB
AABAA. .BAAAA. .ABBBB
AAAAA. .AAAAA. .BBBBB

…(1)…(2)…(3)…
使用.隔开(辣鸡的题面格式化)
其中12是不合法的容器,3是合法的容器
对于每一个部分,他的不稳定性是属于这个部分的所有魔法水晶能量值的极差(最大-最小)
对于整个容器,不稳定性是两部分不稳定性中的最大值
为了知道自己能不能拯救世界,不白白浪费时间,小J想知道整个容器的最小的不稳定值

Input

第一行两个数n,m代表魔法水晶组成的矩阵大小
随后n行,每行m个整数表示魔法水晶的能量值

Output

一行一个整数,表示最小的不稳定值

Sample Input

4 4
1 12 6 11
11 4 2 14
10 1 9 20
4 17 13 10

Sample Output

11

样例说明
BBBA
BBBA
BBBA
BAAA
B极差12-1=11 A极差20-10=10,不稳定值为11,分法不唯一

Data Constraint

对于15%的数据 n,m≤10
对于另15%的数据,n,m中有一个为1
对于55%的数据 n,m≤200(包括最初的15%)
对于所有数据,n,m≤2000,1≤能量值≤1e9

Solution

  • 每多拐一次弯等价于一行中多了一条分界线
  • 而每一行最多只会有一条分界线
  • 容易发现,分成的 A , B A,B A,B 两部分都是类梯形
    在这里插入图片描述

Code

#include<algorithm>
#include<cstdio>

#define fo(i,a,b) for(int i=a;i<=b;++i)
#define fd(i,a,b) for(int i=a;i>=b;--i)

using namespace std;

const int N=2010,inf=1e9;
int n,m,mx,mn,ans,b[N][N];

bool check(int k)
{
	int l=0;
	fo(i,1,n)
	{
		fo(j,1,m) if(mx-b[i][j]>k) l=max(l,j+1);
		fo(j,1,l-1) if(b[i][j]-mn>k) return 0;
	}
	return 1;
}

int ef()
{
	int l=0,r=inf;
	while(l<r)
	{
		int mid=(l+r)>>1;
		if(check(mid)) r=mid;
			else l=mid+1;
	}
	return l;
}

void pre1()
{
	fo(i,1,n/2)
		fo(j,1,m)
			swap(b[i][j],b[n-i+1][j]);
}

void pre2()
{
	fo(i,1,n)
		fo(j,1,m/2)
			swap(b[i][j],b[i][m-j+1]);
}

int main()
{
	freopen("separate.in","r",stdin);
	freopen("separate.out","w",stdout);
	scanf("%d%d",&n,&m);
	ans=inf,mx=-inf,mn=inf;
	fo(i,1,n)
		fo(j,1,m)
		{
			scanf("%d",&b[i][j]);
			mx=max(mx,b[i][j]);
			mn=min(mn,b[i][j]);
		}
	ans=min(ans,ef());
	pre1(),ans=min(ans,ef());
	pre2(),ans=min(ans,ef());
	pre1(),ans=min(ans,ef());
	printf("%d",ans);
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值