当前位置: 首页 > news >正文

01分数规划

好久没发博客了……浅浅复活一下,讲个冷门些的算法。

算法目的:选出k组ai,bi使得  \frac{\sum ai }{\sum bi} 最大。

算法过程:

不妨考虑二分答案,那么答案的形式便是 \frac{\sum ai }{\sum bi}\geq k 的形式,则可通过移项转化为\sum ai - k*\sum bi\geq 0,进一步的,我们可以将求和合并,则有\sum ai-k*bi\geq 0,这便是二分检验的条件,只需挑出满足条件的k组即可,该算法考不出太新鲜的,至多是二分加优化。

那么我们来看一道例题

P4377 [USACO18OPEN] Talent Show G

简化一下题意:选出任意组ai,bi使得\frac{\sum ai }{\sum bi}最大,且\sum bi\geq W。那么看到该限制条件,只需在二分时使用01背包优化即可。最后输出为答案*1000向下取整。

代码:

#include<bits/stdc++.h>
#define ll long long
#define endl '\n'
using namespace std;
const int maxn=1e5+10;
int n,w,a[maxn],b[maxn];
double f[maxn]; 
bool check(double mid){
	for(int i=1;i<=w;i++) f[i]=-1e9;
	for(int i=1;i<=n;i++){
		for(int j=w;~j;j--){
			f[min(w,j+b[i])]=max(f[min(w,j+b[i])],f[j]+a[i]-mid*b[i]);
		}
	}
	return f[w]>=0;
}
int main(){
	ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	cin>>n>>w;
	for(int i=1;i<=n;i++) cin>>b[i]>>a[i];
	double l=0,r=1e6;
	while(r-l>1e-4){
		double mid=(l+r)/2;
		if(check(mid)) l=mid;
		else r=mid;
	}
	cout<<(int)(1000*l)<<endl;
	return 0;
}

相关文章:

  • bash脚本手动清空mysql表数据
  • Java——抽象方法抽象类 接口 详解及综合案例
  • 从零到一:基于DeepSeek-R1的智能贪吃蛇开发实战
  • 【JAVA】常用的JDK8、JDK17 以及 JDK21 的主要新特性和演进过程
  • Ubuntu22安装docker28
  • .DS_Store文件泄露、.git目录泄露、.svn目录泄露漏洞利用工具
  • 驱动-字符设备驱动框架
  • Java学习手册:JVM、JRE和JDK的关系
  • 宇视设备视频平台EasyCVR打造智慧酒店安防体系,筑牢安全防线
  • openEuler Mugen 测试框架
  • 从PDF中提取表格:以GB/T2260—2007为例
  • js实现生肖宜忌展示
  • Linux重启命令(Linux Restart Command)
  • JS包装类型Array
  • 发票查验与OCR识别:财务流程的智慧双保险
  • java+postgresql+swagger-单表批量和循环insert、delete操作(八)
  • 人工智能:GPT技术应用与未来展望
  • c++进阶之----c++11(包装器)
  • Elasticsearch 官网阅读学习笔记01
  • SpringBoot 数据库MySql的读写分离 多数据源 Shardingsphere高并发优化