分巧克力、扫地机器人(二分)

分巧克力“蓝桥杯”练习系统 (lanqiao.cn)

 

解析:公式:(长/当前最大边长)*(宽/当前最大变长),这个很容易推出来的。就比如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;
}

扫地机器人“蓝桥杯”练习系统 (lanqiao.cn)

 

解析:二分,用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;
}

### Java 实现巧克力问题的二分算法 #### 1. 问题描述 给定若干块不同尺寸的巧克力,每块巧克力由两个整数表示其长度和宽度。目标是找到一个最大的正方形边长 \( d \),使得可以从这些巧克力中切割出尽可能多的小朋友数量相同的正方形巧克力。 #### 2. 解决方案概述 为了高效解决这个问题,采用二分查找的方法来确定最大可能的正方形边长 \( d \)。通过不断调整上下限并验证当前中间值是否满足条件,最终得到最优解。 #### 3. 算法步骤说明 - 定义变量 `low` 和 `high` 别初始化为最小可能值(通常是1)以及所有矩形中最短的一条边作为初始上限。 - 计算中间值 `mid = low + (high - low >> 1)` 并检查能否按照此大小配足够的份数。 - 如果可以,则尝试更大的值;反之缩小范围直到收敛于最佳答案。 #### 4. 关键函数解析 定义辅助方法用于判断特定尺寸下能否成功割足够数量: ```java private static boolean canDivide(int[][] chocolates, int mid, int k){ int count = 0; for (int[] chocolate : chocolates){ count += ((chocolate[0] / mid) * (chocolate[1] / mid)); if(count >= k) return true; // 提前终止循环提高效率 } return false; } ``` 该逻辑实现了对于每一个候选边长 `mid` 的可行性评估,并利用提前退出机制减少不必要的计算开销[^3]。 #### 5. 主体代码实现 以下是完整的Java程序清单,展示了如何应用上述思路解决问题: ```java import java.util.*; public class ChocolateDivision { private static final Scanner scanner = new Scanner(System.in); public static void main(String[] args) { List<int[]> inputChocolates = readInput(); System.out.println(findMaxSquareSize(inputChocolates.toArray(new int[inputChocolates.size()][]), getK())); } private static List<int[]> readInput(){ int n = Integer.parseInt(scanner.nextLine()); List<int[]> result = new ArrayList<>(); while(n-- > 0){ String[] line = scanner.nextLine().split(" "); result.add(new int[]{Integer.parseInt(line[0]), Integer.parseInt(line[1])}); } return result; } private static int findMaxSquareSize(int[][] chocolates, int k){ Arrays.sort(chocolates, Comparator.comparingInt(o -> Math.min(o[0], o[1]))); int minEdgeLength = 1; int maxPossibleEdgeLength = chocolates[chocolates.length - 1][0]; int bestFit = binarySearchForBestFit(minEdgeLength, maxPossibleEdgeLength, chocolates, k); return bestFit; } private static int binarySearchForBestFit(int low, int high, int[][] chocolates, int k){ while(low <= high){ int mid = low + ((high - low) >>> 1); if(canDivide(chocolates, mid, k)){ low = mid + 1; }else{ high = mid - 1; } } return high; } private static boolean canDivide(int[][] chocolates, int mid, int k){ long piecesCount = 0L; for(var item : chocolates){ piecesCount += (((item[0]/mid)*(item[1]/mid))); if(piecesCount>=k)return true; } return false; } private static int getK() { return Integer.parseInt(scanner.nextLine()); } } ``` 这段代码首先读入输入数据,接着调用核心处理流程 `findMaxSquareSize()` 来执行主要运算过程。其中包含了对原始数据按最短边排序的操作以便更合理地设定搜索区间边界。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_谦言万语

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值