01分數規劃入門

2022-02-02 07:36:13 字數 4423 閱讀 4592

01分數規劃是這樣的一類問題,有一堆物品,每乙個物品有乙個收益ai,乙個代價bi,我們要求乙個方案使選擇的$\sum/\sum$最大。

首先我們來一道例題吧,01分數規劃的大體方法都是一樣的。

例1 dropping tests poj2976

給出n個物品,每個物品有兩個屬性a和b,選擇n-k個元素,詢問$\sum/\sum$的最大值。

1<=n<=1000,0<=k首先這題顯然是茲磁二分的,而$\sum/\sum \geq x$就等價於$\sum-x\sum \geq 0$。

所以我們發現二分完把ai-x*bi排序後把最大的n-k個選出來就行了。

#include #include 

#include

#include

#include

#include

#include

#include

#include

#include

using

namespace

std;

int n,k,a[2333],b[2333

];double ps[2333

];bool ok(double

x)void

sol()

printf(

"%.0lf\n

",l*100);}

intmain()

但是還有一種神奇的做法,既然我們可以二分乙個值,而且得出乙個更優的解,那麼我們就可以在這個解的基礎上繼續做,直到滿足精度。

#include #include 

#include

#include

#include

#include

#include

#include

#include

#include

using

namespace

std;

intn,k;

struct pro s[233333

];bool

operator

< (pro a,pro b)

double sol(double

x)void

sol()

while(fabs(l-ans)>1e-6

);

if(l>1) l=1

;

if(l<0) l=0

; printf(

"%.0lf\n

",l*100);}

intmain()

例2 desert king poj2728

(模型有轉化)

給出乙個n個點的完全圖,每條邊有兩個權值cost和len。

求乙個生成樹使$\frac}}$最小。

2<=n<=1000

還是二分答案x,把每條邊邊權設為cost-x*len,跑最小生成樹,判答案的正負。建議用prim跑,複雜度比較科學。

#include #include 

#include

#include

#include

#include

#include

#include

#include

#include

using

namespace

std;

typedef

long

double

ld;#define sz 1066

intn,xx[sz],yy[sz],hh[sz],fm[sz];

bool

del[sz];

ld mind[sz],d[sz][sz],d1[sz][sz],d2[sz][sz];

ld sqr(ld x)

ld abs(ld x)

bool

ok(ld x)

for(int i=0;i<=n;i++) mind[i]=1000000000, del[i]=0

; mind[

1]=0; fm[1]=0

; ld ans=0

;

for(int i=1;i<=n;i++)

ans+=d[fm[mp]][mp]; del[mp]=1

;

for(int j=1;j<=n;j++)

}return ans<=0;}

void

sol()

}ld l=0,r=1000000000

;

while(r-l>1e-6

)

printf(

"%.3lf\n

",(double

)l);

}int

main()

直接迭代

#include #include 

#include

#include

#include

#include

#include

#include

#include

#include

using

namespace

std;

#define sz 1066

intn,xx[sz],yy[sz],hh[sz],fm[sz];

bool

del[sz];

double

mind[sz],d[sz][sz],d1[sz][sz],d2[sz][sz];

double sqr(double x)

double abs(double x)

double sol(double

x)

for(int i=0;i<=n;i++) mind[i]=1000000000, del[i]=0

; mind[

1]=0; fm[1]=0

;

double aa=0,bb=0

;

for(int i=1;i<=n;i++)

aa+=d1[fm[mp]][mp];

bb+=d2[fm[mp]][mp];

del[mp]=1

;

for(int j=1;j<=n;j++)

}return aa/bb;

}void

sol()

}double l,ans=0

;

dowhile(fabs(l-ans)>1e-6

); printf(

"%.3lf\n

",l);

}int

main()

例3 sightseeing cows poj3621

給出乙個有l個點p條邊的有向圖,每個點上有點權f,每條邊上有邊權t。

求乙個迴路使$\frac}}$最大。

2<=l<=1000,2<=p<=5000。

因為環上邊和點數相等,我們可以直接把邊權當做花費,入點的點權當作收入。

然後還是二分答案建圖,判圖中有沒有正環。取個反就成了判負環。

dfs版spfa即可。

#include #include 

#include

#include

#include

#include

#include

#include

#include

#include

using

namespace

std;

#define sz 666666

int n,m,v[sz],fst[sz],vb[sz],nxt[sz],vc[sz],m=0

,x;bool vis[sz],fh=0

;double

dist[sz];

void adde(int a,int b,int c)

void dfs(int p,double

x) dist[vb[e]]=c+dist[p];

dfs(vb[e],x);

if(fh) return

; }

vis[p]=0;}

bool ok(double

x)

return0;

}int

main()

double l=0,r=1000000000

;

while(r-l>1e-6

)

printf(

"%.2lf\n

",l);

}

迭代的話…似乎不太好寫,就算了吧

0 1分數規劃

題目鏈結 中文鏈結 附一篇大佬部落格感覺講的不錯 0 1分數規劃,不妨設 l a i b i 題目要求要讓結果最大,那麼就是l最大最終移相化簡可得 a i l b i 0,因為a 和b都是已知所以我們可以直接列舉l,當我們所求的值大於零說明l還有更優解當小於零時l沒有最優解。直接二分即可 inclu...

01分數規劃

01分數規劃,就是這樣乙個東西 max frac 其中 xi in 簡而言之,就是在n個物品中選出任意幾個 或者可以有限制選多少個 使得其兩種權值a,b的比值最大 這樣的問題可以二分解決 假如有這樣一道裸題 poj2976,選n k個物品使得比值最大 我們二分出r,若存在 frac r 則r可行 變...

01分數規劃

已經接觸過01分數規劃但是只知道二分寫法 實際求解略慢 dinkelbach演算法還是值得一學的。上一道裸的01分數規劃吧。poj x陣列代表我們選或者不選 0,1構成 r sigma a i x i sigma b i x i 變形 設f v 為 sigma a i x i sigma b i x...