poj 2976 && poj 2728 && poj3621 && bzoj 1486 01分数规划
来源:互联网 发布:淘宝客服下班结束语 编辑:程序博客网 时间:2024/05/18 00:48
关于01分数规划的具体讲解和例题分析,推荐相当好的博客:http://www.cnblogs.com/perseawe/archive/2012/05/03/01fsgh.html
这里不再赘述
所以这里只是简单粗暴的贴代码
poj 2976
题目的要求是求比值最大,限制是所取得数量为n-k,所以只需要将d排序取前n-k个即可
注意:数据结束的条件是(n=0) && (k=0),但是在读入的时候不能判断 while (n<>0) and (k<>0) ,因为会存在合法的输入使得 n<>0 && k=0 ,所以数据结束的条件是(n<>0)
二分方法:
const eps=1e-6;var n,m,k :longint; i :longint; tmp,l,r,mid :double; a,b :array[0..1010] of longint; d :array[0..1010] of double;procedure sort(l,r:longint);var i,j:longint; x,y:double;begin i:=l; j:=r; x:=d[(l+r)>>1]; while (i<=j) do begin while d[i]>x do inc(i); while d[j]<x do dec(j); if i<=j then begin y:=d[i]; d[i]:=d[j]; d[j]:=y; inc(i); dec(j); end; end; if i<r then sort(i,r); if j>l then sort(l,j);end;begin read(n,k); while (n<>0) do begin for i:=1 to n do read(a[i]); for i:=1 to n do read(b[i]); m:=n-k; r:=0; for i:=1 to n do if a[i]/b[i]>r then r:=a[i]/b[i]; l:=0; while (r-l>=eps) do begin mid:=(l+r)/2; for i:=1 to n do d[i]:=a[i]-mid*b[i]; sort(1,n); tmp:=0; for i:=1 to m do tmp:=tmp+d[i]; if tmp>0 then l:=mid else r:=mid; end; writeln(round(l*100)); read(n,k); end;end.
Dinkelbach算法:
const eps=1e-6;var n,m,k :longint; i :longint; l,ans :double; p,q :int64; a,b,c :array[0..1010] of longint; d :array[0..1010] of double;procedure sort(l,r:longint);var i,j:longint; z:longint; x,y:double;begin i:=l; j:=r; x:=d[(l+r)>>1]; while (i<=j) do begin while d[i]>x do inc(i); while d[j]<x do dec(j); if i<=j then begin y:=d[i]; d[i]:=d[j]; d[j]:=y; z:=c[i]; c[i]:=c[j]; c[j]:=z; inc(i); dec(j); end; end; if i<r then sort(i,r); if j>l then sort(l,j);end;begin read(n,k); while (n<>0) do begin for i:=1 to n do read(a[i]); for i:=1 to n do read(b[i]); m:=n-k; l:=1; repeat ans:=l; for i:=1 to n do begin d[i]:=a[i]-l*b[i]; c[i]:=i; end; sort(1,n); p:=0; q:=0; for i:=1 to m do begin inc(p,a[c[i]]); inc(q,b[c[i]]); end; l:=p/q; until abs(l-ans)<eps; writeln(round(ans*100)); read(n,k); end;end.
poj 2728
最优比率生成树,题目要求是比率最小,题目的限制是树,所以我们用prim来记录我们选择的边(这种图真的不建议用kruscal...),Dinkelbach算法会比二分快,所以这里就只写了Dinkelbach算法,注意每次都要更新a、b、d数组const eps=1e-6;var n,pos,ta :longint; l,ans,p,q,tt :double; tb,td :double; i,j :longint; x,y,z,a :array[0..1010] of longint; flag :array[0..1010] of boolean; b,d :array[0..1010] of double;begin read(n); while (n<>0) do begin for i:=1 to n do read(x[i],y[i],z[i]); l:=0; repeat ans:=l; p:=0; q:=0; for i:=2 to n do begin a[i]:=abs(z[i]-z[1]); b[i]:=sqrt(sqr(x[i]-x[1])+sqr(y[i]-y[1])); d[i]:=a[i]-l*b[i]; end; fillchar(flag,sizeof(flag),false); flag[1]:=true; for i:=1 to n-1 do begin tt:=1e9; for j:=2 to n do if not flag[j] and (d[j]<tt) then begin pos:=j; tt:=d[j]; end; flag[pos]:=true; p:=p+a[pos]; q:=q+b[pos]; for j:=2 to n do if not flag[j] then begin ta:=abs(z[j]-z[pos]); tb:=sqrt(sqr(x[j]-x[pos])+sqr(y[j]-y[pos])); td:=ta-l*tb; if td<d[j] then begin d[j]:=td; a[j]:=ta; b[j]:=tb; end; end; end; l:=p/q; until abs(l-ans)<eps; writeln(ans:0:3); read(n); end;end.
最优比率环,题目要求比率最大,没啥限制,只要存在正环就说明还有更优的答案。将边建成负的,这样判正环就变成了判负环,由于数据范围并不是很大,所以就用了Bellman_ford。这类题只用二分
const eps=1e-6;var n,m :longint; l,r,mid :double; i :longint; a :array[0..1010] of longint; x,y,b :array[0..5010] of longint; d :array[0..5010] of double; dis :array[0..1010] of double;function bellman_ford(l:double):boolean;var i,j:longint; flag:boolean;begin for i:=1 to m do d[i]:=-(a[x[i]]-l*b[i]); for i:=1 to n do dis[i]:=0; for i:=1 to n do begin flag:=false; for j:=1 to m do if (dis[x[j]]+d[j]<dis[y[j]]) then begin dis[y[j]]:=dis[x[j]]+d[j]; flag:=true; end; if not flag then exit(false); end; exit(true);end;begin read(n,m); for i:=1 to n do read(a[i]); for i:=1 to m do read(x[i],y[i],b[i]); // l:=0; r:=20000; while (r-l>=eps) do begin mid:=(l+r)/2; if bellman_ford(mid) then l:=mid else r:=mid; end; if l>eps then writeln(l:0:2) else writeln(0);end.
bzoj 1486
最优比率环,题目要求比率最小,也没啥其他限制。这次就直接建边判负环就行了,这数据范围相当卡,所以用dfs版spfa判负环...
const eps=1e-9;var n,m,ll,x,y,z :longint; i :longint; l,r,mid :double; vis :array[0..3010] of boolean; last :array[0..3010] of longint; pre,other,len :array[0..10010] of longint; dis :array[0..3010] of double; flag :boolean;procedure connect(x,y,z:longint);begin inc(ll); pre[ll]:=last[x]; last[x]:=ll; other[ll]:=y; len[ll]:=z;end;procedure dfs(x:longint;l:double);var p,q:longint;begin if flag then exit; vis[x]:=true; q:=last[x]; while (q<>0) do begin if flag then exit; p:=other[q]; if dis[p]>dis[x]+len[q]-l then begin dis[p]:=dis[x]+len[q]-l; if vis[p] then begin flag:=true;exit; end else dfs(p,l); end; q:=pre[q]; end; vis[x]:=false;end;function check(x:double):boolean;var i:longint;begin flag:=false; for i:=1 to n do dis[i]:=0; for i:=1 to n do vis[i]:=false; for i:=1 to n do begin dfs(i,x); if flag then exit(true); end; exit(false);end;begin read(n,m); for i:=1 to m do begin read(x,y,z); connect(x,y,z); end; l:=0; r:=1e7; while (r-l>=eps) do begin mid:=(l+r)/2; if check(mid) then r:=mid else l:=mid; end; writeln(r:0:8);end.——by Eirlys
0 0
- poj 2976 && poj 2728 && poj3621 && bzoj 1486 01分数规划
- POJ 2976 01分数规划
- 01 分数规划 poj 2976
- poj 2976 分数规划
- 01分数规划【最优比率环】--poj3621
- poj3621 Sightseeing Cows --- 01分数规划
- [POJ3621]Sightseeing Cows(01分数规划)
- 【POJ 2728】[01分数规划]Desert King
- POJ 2976 Dropping tests 01分数规划
- POJ 2976 Dropping tests 01分数规划
- poj-2976-Dropping tests-01分数规划
- POJ 2976 Dropping tests 01分数规划
- POJ 2976 01分数规划基础题目
- 【POJ】2976 Dropping tests 01分数规划
- [poj 2976]Dropping tests 01分数规划
- poj 2976(01分数规划最基础)
- POJ 2976,3111 01分数规划
- POJ 2976 Dropping tests (01分数规划)
- 安卓开发之WebView控件只用
- Spark磁盘空间满了
- Ngrok穿透工具的使用
- 世界上主流的五大浏览器及其内核
- highcharts图表:如何配置坐标轴数据过大是否折算进行单位(k,M,G,T,P,E)替换
- poj 2976 && poj 2728 && poj3621 && bzoj 1486 01分数规划
- 蓝桥杯2017模拟赛-还款计算
- STL在使用算法竞赛中的使用方法 (教程+未完成)
- POJ 2385 Apple Catching
- java虚拟机随手笔记(4)内存调优与案例分析
- 动态配置配置文件路径
- MyBatis总结
- Android SDK Manager和AVD Manager使用
- uva 725(暴力)