分巧克力(二分查找)

题目名字

题目链接

题意

一共有n块巧克力和m个小朋友,要把这n块巧克力切成相等大小 的正方形分给这m个小朋友,尽可能分的大;

思路

  1. 利用二分,在二分模板里面进行计算
  2. 输入每个巧克力的长宽的时候用数组分开输入,不用设置二维数组
  3. 定义一个sum来计算巧克力的数量,用每块巧克力的长与宽来除mid,并且相乘,判断sum是否大于等于m,如果是的话将边界往左移,使巧克力的边长,变大反之就使巧克力边长变小,进行判断,就能找出最大的边长

算法一:二分

代码
 #include<iostream>
using namespace std;
int main(){
	int n,m;
	cin>>n>>m;
	int h[n],w[n];
	for(int i=0;i<n;i++){
		cin>>h[i]>>w[i];
	}
	int l=1,r=100005;
	int ans=0;
	while(l<=r){
		int mid=(l+r)/2;
		int cnt=0;
		for(int i=0;i<n;i++){
			cnt+=(h[i]/mid)*(w[i]/mid); //这一步是在算当分的巧克力边长为mid的时候,拥有的这一块巧克力可以分多少块;
		}
		if(cnt>=m){
			l=mid+1;
			ans=mid;//当在这个范围内可以切需要的巧克力量时,此时mid就可以当做切得边长;
		}
		else{
			r=mid-1;
		}
	}
	cout<<ans;
	return 0;
}


 

算法二:二分

思路:

OMG,看到题目呢就要判断出是二分题,因为求最小值最大化,题目要求在首先写下伪代码,1.确认二分谁(边长)2.确定验证函数(切k块)3.确定判断范围 然后进行代码编写
|
确认数据大小,考虑是否会溢出用longlong,要找到最大的边界用max函数

代码
 #include<iostream>
#include<algorithm>
//二分什么
//确定验证的函数
//确定搜索范围 
using namespace std;
const int N=1e5+5;

int h[N],w[N]; 

int main(){
	int n,k;
	cin>>n>>k;
	int max_side=0;
	
	for(int i=0;i<n;i++){
	cin>>h[i]>>w[i];
	max_side=max(max_side,min(h[i],w[i]));//在所有长宽里,找出宽,然后再找最长的宽, 
	}
	
	//计算巧克力数量 
	int count=0;//计算最大的边 
	int l=0,r=max_side;
	//int l=0,r=100005;
	
	while(l<=r){
	int mid=l+r>>1;
	long long int ans=0;
		for(int i=0;i<n&&ans<k;i++){
			ans+=(long long)(h[i]/mid)*(w[i]/mid);//计算所有巧克力都能切割的最大边 
			} 
		if(ans>=k)//判断所有巧克力切块数量是否符合 
		{
				l=mid+1;
				count=mid;
		} 
			else{
				r=mid-1;
			}
	}
	
	 cout<<count;
}

总结

第一对二分题目的基础思路不清晰
第二是找最大边界的时候需要用到max函数 但是 不会,所以试图用两个bool判断条件来写以失败告终
第三是while和for循环嵌套的位置,把for循环放在里面是为了判断所有巧克力是否能在此时mid的值里面被切割到需要的数量,并且二分判断是在for循环外的,因为 不需要每个都判断,第一次写反了导致整个逻辑的错误,下次写之前判断好
第四ans用来计数,是需要在每次二分迭代前重置的!否则一直累加造成错误
|
主要就是写题要有基本框架,每个步骤是为了什么,每个数据的作用,对于while里面需要加for循环的题目要更加清晰,以至不会出现这种莫名其妙的错误(真的很难查出来救命。。)
粗心的问题,l和r的值

新知识点

max和min函数maxside=max(maxside,min(h[i],w[i]))

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值