解析:公式:(长/当前最大边长)*(宽/当前最大变长),这个很容易推出来的。就比如6 * 5划成
2 * 2,有(6/2)*(5/2)= 6块。根据这个公式进行二分答案即可
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long LL;
LL s,n,k;
int h[100005],w[100005];
bool check(int x) {
int cnt=0;
for(int i=1; i<=n; i++)
cnt+=(h[i]/x)*(w[i]/x);//由样例中可得此式子
return cnt>=k;//与题意相符才为真
}
int main() {
int ans,l=1,r=1;
cin>>n>>k;
for(int i=1; i<=n; i++) {
cin>>h[i]>>w[i];
r=max(r,max(h[i],w[i]));//减少一点工作量(最大也只能切成这样,可能还切不出)
}
while(l<=r) {
int mid=(l+r)/2;
if(check(mid)) {
ans=mid;
l=mid+1;//最大边长太小了,往右边继续找
} else r=mid-1;//太大了,左边找
}
cout<<ans;
return 0;
}
解析:二分,用check找区间长度,判定方式需要分类讨论,代码有解释
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long LL;
int n,k;
int a[100005];
//求小于等于的最大值
//s是到达的位置,x是需要扫的长度
bool check(int x) {
int s=0;//清扫到哪个位置
for(int i=1; i<=k; i++) {
if(a[i]<=s+x) { //a[i]在需要扫的范围内
if(a[i]<=s) s=a[i]+x-1; //a[i]一开始就开始扫描位置的左侧,记得减去自己
else s+=x;//a[i]在s右边,左边还需要扫,所以相当于s+x
}
else return false;//a[i]>=s+x表示区间长度太短了,够不着
}
return s>=n;
}
int main() {
cin>>n>>k;
for(int i=1; i<=k; i++)
cin>>a[i];
sort(a+1,a+k+1);
int l=1,r=n,ans;
//二分板
while(l<=r) {
int mid=l+(r-l)/2;
if(check(mid)) {
ans=mid;
r=mid-1;//大了往左靠
}
else l=mid+1;//小了往右靠
}
cout<<(ans-1)*2;
return 0;
}