01分数规划
https://blog.csdn.net/hzoi_ztx/article/details/54898323
01分数规划问题主要包含以下几个问题:
- 一般的01分数规划
- 最优比率生成树
- 最优比率环
关于二分判断条件的理解。
给出几道例题:一、POJ-2976
入门

#include <cstdio> #include <iostream> #include <cstring> #include <algorithm> #include <queue> #include <cctype> #include <cmath> #include <time.h> #include <map> #include <set> #include <vector> using namespace std; #define ms(a,b) memset(a,b,sizeof(a)) typedef long long ll; const double eps=1e-7; int n,k; double a[1010],b[1010],d[1010]; inline int read() { int X=0,w=0; char ch=0; while(!isdigit(ch)) {w|=ch=='-';ch=getchar();} while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar(); return w?-X:X; } int main() { while (1) { n=read(),k=read(); if (n==0 && k==0) break; for (int i=1;i<=n;i++) scanf("%lf",&a[i]); for (int i=1;i<=n;i++) scanf("%lf",&b[i]); double l=0.0,r=1.0,mid; while (r-l>eps) { mid=(l+r)/2; for (int i=1;i<=n;i++) d[i]=a[i]-mid*b[i]; sort(d+1,d+1+n); double sum=0.0; for (int i=k+1;i<=n;i++) sum+=d[i]; if (sum>0) l=mid; else r=mid; } printf("%.0f\n",mid*100); } return 0; }
也是入门

#include <cstdio> #include <iostream> #include <cstring> #include <algorithm> #include <queue> #include <cctype> #include <cmath> #include <time.h> #include <map> #include <set> #include <vector> using namespace std; #define ms(a,b) memset(a,b,sizeof(a)) typedef long long ll; const int maxn = 50005; const double eps = 1e-9; ll gcd(ll x,ll y){return y?gcd(y,x%y):x;} struct node { int w,p; double val; bool operator < (const node& T) const{ return val>T.val; } }b[maxn]; double mid; ll anss,ansx,tmps,tmpx; int n,k; bool check() { int tot=0; for(int i=0;i<n;i++)b[i].val = 1.0*b[i].p-b[i].w*mid; sort(b,b+n); double sum=0; tmps=0,tmpx=0; for(int i=0;i<k;i++)sum+=b[i].val,tmps+=b[i].p,tmpx+=b[i].w; if(sum-0>=eps)return true; return false; } int main() { scanf("%d%d",&n,&k); for(int i=0;i<n;i++) scanf("%d%d",&b[i].w,&b[i].p); double l=0,r=500000; for(int i=0;i<100;i++) { mid=(l+r)/2; if(check())l=mid,anss=tmps,ansx=tmpx; else r=mid; } ll tmp=gcd(anss,ansx); anss/=tmp,ansx/=tmp; printf("%lld/%lld\n",anss,ansx); return 0; }
大意:给定一张图,每条边有一个收益值和一个花费值, 求一个生成树,要求花费/收益最小,输出这个值
分析:现在的限制就有点复杂了,要求解必须是一棵生成 树。而且这道题目要求的花费/收益最小,当然你求收益/ 花费最大然后反过来也是可以的,注意处理花费为0的情 况。如果求最小的,处理方法是也类似的,先求个D,然 后做一次最小生成树,显然得到的就是函数值。
大意:给定一张图,边上有花费,点上有收益,点可以多 次经过,但是收益不叠加,边也可以多次经过,但是费用 叠加。求一个环使得收益和/花费和最大,输出这个比值。
分析:比上面更加的恶心了。先不说环的问题,就是花费 和收益不在一处也令人蛋疼。这时候需要用到几个转化和 结论。
首先的一个结论就是,不会存在环套环的问题,即最优的方 案一定是一个单独的环,而不是大环套着小环的形式。这个的
证明其实非常的简单,大家可以自己想一下(提示,将大环上 的收益和记为x1,花费为y1,小环上的为x2,y2。重叠部分的花
费为S。表示出来分类讨论即可)。有了这个结论,我们就可以 将花费和收益都转移到边上来了,因为答案最终一定是一个环,
所以我们将每一条边的收益规定为其终点的收益,这样一个环 上所有的花费和收益都能够被正确的统计。
解决了蛋疼的问题之后,就是01分数规划的部分了,我们只 需要计算出D数组后找找有没有正权环即可,不过这样不太好, 不是我们熟悉的问题,将D数组全部取反之后,问题转换为查找 有没有负权环,用spfa或是bellman_ford都可以。

#include<iostream> #include<algorithm> #include<cstring> #include<cstdio> #include<cmath> #define N 100010 using namespace std; const double eps=1e-5; struct edge { int v,nxt,w; double c; } e[N<<1]; int head[N],f[N]; bool vis[N]; double dis[N]; int n,m,mct,u,v,w; inline int read() { int x=0,f=1;char c=getchar(); while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} return x*f; } void add(int u,int v,int w) { e[++mct].v=v;e[mct].nxt=head[u];e[mct].w=w;head[u]=mct; } bool spfa(int u) { vis[u]=1; for(int i=head[u]; i; i=e[i].nxt) { int v=e[i].v; if(dis[v]>dis[u]+e[i].c) { dis[v]=dis[u]+e[i].c; if(vis[v] || spfa(v)) { vis[v]=0; return 1; } } }vis[u]=0;return 0; } void judge(double r) { for(int i=1; i<=mct; i++) e[i].c=(double)e[i].w*r-f[e[i].v]; return; } bool check() { for(int i=1; i<=n; i++) if(spfa(i))return 1; return 0; } int main() { n=read();m=read(); for(int i=1; i<=n; i++) f[i]=read(); for(int i=1; i<=m; i++) { u=read();v=read();w=read(); add(u,v,w); } double l=0,r=100000,ans; while(r-l>eps) { double mid=(l+r)/2; judge(mid); if(check()) { ans=mid;l=mid; } else r=mid; } printf("%.2f\n",ans); return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人