2022杭电多校八 1011-Stormwind(贪心)

题目链接:杭电多校8 - Virtual Judge

 题意:一个n*m的长方形,可以沿水平或竖直方向画若干条线,每条线的两端点都在长方形边界上,且线要与长方形的某一边平行且端点位于格点上。要求这些线划分出的每个小长方形面积都大于等于k,求最多可以画几条线。

分析:先来看这么一个问题:一根长为n的绳子,我们要用剪刀将其剪断,要保证每段长度不能小于m,求最多能剪几次?

答案是n/m-1,而不是n/m的下取整,因为我们要保证每一段长度都不能小于m,所以如果剪完最后一次后会使得最后剩余一段长度小于m的绳子,那么这一次我们是不能剪的,所以就需要减1,知道了这个我们再来分析一下这个问题:
我们可以来O(min(k,n))枚举矩形的高h,那么对于每次的高h,为了使得矩形的面积不小于k,那么至少需要的宽度就是w=(k-1)/h+1,那么为了使得切的次数是最大的,那么我们显然宽度越小越好,因为我们切的次数是m/w-1,这显然是一个单调函数,随着w的增大而减小,所以对于每个高已经固定的情况,我们都能O(1)确定切的次数,所以总的复杂度就是O(min(k,n)),对于高为h,宽为b的情况,我们切的次数最多是(n/h+m/b-2),需要注意的是我们的h是小于n的,这个我们可以在for循环的时候就直接设定边界,而b是小于m的,这个需要我们特判一下,细节见代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<map>
#include<queue>
#include<vector>
#include<cmath>
using namespace std;
long long n,m,k;
long long cal(long long h)
{
	long long ans=n/h-1; 
	long long b=(k-1)/h+1;//求解最小的b满足h*b>=k 
	if(b>m) return 0;
	return (ans+(m/b-1));
}
int main()
{
	int T;
	cin>>T;
	while(T--)
	{
		scanf("%lld%lld%lld",&n,&m,&k);
		long long ans=0;
		for(int i=1;i<=min(k,n);i++)
			ans=max(ans,cal(i));
		cout<<ans<<endl;
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值