日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

分治 —— 01 分数规划

發布時間:2025/3/17 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 分治 —— 01 分数规划 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

【概述】

分數規劃的一般形式為:

特別的,當??時,稱為 01 分數規劃

簡單來說,就是有一些二元組 (a[i],b[i]),現在從中選擇某些二元組,使得??最大或最小

這一類題通用的解法是利用二分法來解決:

假設 x 為最優解,對應的最優函數值為?λ,那么有:

即:

于是可以構造函數?

當??時,此時 λ 即為最優解

也就是說,當某一個值 λ?滿足上述式子的時候,就是要求的值,因此可以直接二分答案:當上述式子 >0,說明答案小了,更改左區間;當上述式子 <0,說明答案大了,更改右區間

double left=0,right=1; while(left-right<=EPS) {double mid=(left+right)/2;double G=INF;for(int i=1;i<=n;i++) G=min(G, a[i]-mid*b[i]);if(judge(G))left=mid;elseright=mid; }

【Dinkelbach 算法】

對于 01 規劃問題,除了利用基本的二分答案來解決外,還有一個常用的算法:Dinkelbach 算法

Dinkelbach 算法是一種的迭代算法,其核心思想是:對于一個值 λ ,我們找到其最優解 x,然后再用解 x 來代替 λ ,即令?λ=f(x),然后繼續迭代,直到 λ 的值不再變動,此時即得出最優解。

double init=0.5;//初始值可隨意設置 while(fabs(init-res)>EPS) {res=left;//記錄比率for(int i=1;i<=n;i++)//計算函數G G=min/max(G,a[i]-init*b[i]);double p=0,q=0;for(int i=1;i<=m;i++){//計算新比率p+=a[i];q+=b[i];}init=p/q;//更新比率 }

【常見模型】

01 規劃問題,除了上述的基本模型外,還有以下三種常見的模型

1.最優比率生成樹

1)問題:對于給定的帶權無向圖 G,對于圖中的每條邊 edge[i],都有 value[i] 與 cost[i],現在要求一棵生成樹 T,使得?最大化或最小化,這個生成樹 T,即為最優比率生成樹

2)解決:如果一條邊 edge[i]∈T,那么 x[i]=1,否則 x[i]=0,因此可以直接套用 01 規劃分數模型

二分法:二分答案 mid,對邊重賦值 weight[i]=value[i]-mid*cost[i],由于是生成樹,因此邊的數量固定為 n-1 條,因此如果要最大化,只要選取前 n-1 大的 weight[i],也即求最大生成樹,如果要最小化,就求最小生成樹,最后按最大生成樹的權值正負性進行二分

Dinkelbach 算法:設置初始值 init,對邊同樣重賦值 weight[i]=value[i]-init*cost[i],對于最大化來說,求最大生成樹,找到其邊集,對其邊集找橫截距當作下一次的答案,進行迭代

2.最優比率環

1)問題:給定一個存在環的有向圖 G,每個點都有一個權值 value[i],每條邊也有一條權值 cost[i],現在要求一個環 C,使得環的?最大化或最小化(在一個環中,點數與邊數是相同的),這個環,即為最優比率環

2)解決:

假設答案為 x,那么對于任意一個環

當要最大化時,有:,化簡得:

即:

同理,當要最小化時,有:

因此可以直接套用 01 規劃分數模型

二分法:設當前答案為 mid,當 mid<x 時,至少存在一個環,使得?,即存在負權回路;當 mid>=x 時,不存在負環,因此可在利用 SPFA 求負環的過程中對邊進行重賦值,從而進行二分,即如果存在負環,即增大下界,若一直不可行,則無解

Dinkelbach 算法:由于使用 Dinkelbach 算法需要在不斷迭代的過程中記錄負環,實現較為復雜,因此一般在該模型中不采用該方法

3.最大密度子圖

`1)問題:給出一個 n 個點 m 條邊的無向圖,現在要選擇一個子圖,使得這個子圖中邊數與點數的比例最大化,這個子圖,即為最大密度子圖

2)解決:

設 g 為最大比率,若要找一個最大密度子圖,那么可以參考 01分數規劃的基本模型來構造一個函數 h(g)=|E'|-g*|V'|,當 h(g)=0 時,g 即為最優值

關于兩種解法的詳細證明參見?胡伯濤的《最小割模型在信息學競賽中的應用》:點擊這里

二分+最大權閉合圖:

可以發現,邊與點具有依賴關系,即邊存在的必要條件是點的存在,那么我們可以將邊看作點,根據 g 的值來構建一個新圖,即:將原圖中所有代表邊的點向他的兩個端點連接一條有向邊

那么可以直觀的看出,如果選擇一條邊,那么這條邊的兩個端點必然也被選擇,也就是一個閉合子圖的模型

因此,在二分 g 的過程中,不斷的建圖來判斷 g 的正負從而調整邊界即可

void makeMap(double g) {memset(head,-1,sizeof(head)); tot=0;for(int i=1;i<=n;i++)//原圖中的點到匯點 addedge(i,T,g); for(int i=0;i<m;i++) { //源點到原圖中的每條邊addedge(S,n+i+1,1.0);//原圖中的每條邊到之間建邊addedge(n+i+1,pastEdge[i].first,INF); addedge(n+i+1,pastEdge[i].second,INF); } }

二分+最小割:

設 g 為最大比率,在建圖時從源點到各點連接一條容量為 m?的單向邊,從各點到匯點連接一條容量為 m+2*g-degree[i] 的單向邊,其中 degree[i] 代表第 i 個點的度數,這樣以后對這個圖求最小割,那么?h(g)=(n*m-maxFlow)/2

因此在二分時,通過?g 值求出的最小割來判斷正負,于是根據這個結果的正負就可以修改左右邊界,直到達到一個最優值

void makeMap(double g) {memset(head,-1,sizeof(head)); tot=0;for (int i = 1; i <= n; i++) {//原圖中的點addedge(S, i, m * 1.0);addedge(i, T, m + 2 * g - degree[i]);}for (int i = 0; i < m; i++) {//原圖中的邊addedge(pastEdge[i].first, pastEdge[i].second, 1.0);addedge(pastEdge[i].second, pastEdge[i].first, 1.0);} }

【例題】

  • Dropping tests(POJ-2976)(標準模型+二分解法):點擊這里
  • Dropping tests(POJ-2976)(標準模型+Dinkelbach 算法):點擊這里
  • Desert King(POJ-2728)(最優比率生成樹+二分解法):點擊這里
  • Desert King(POJ-2728)(最優比率生成樹+Dinkelbach 算法):點擊這里
  • Sightseeing Cows(POJ-3621)(最優比率環+二分解法):點擊這里
  • Hard Life(POJ-3155)(最大密度子圖+最大權閉合圖):點擊這里
  • Hard Life(POJ-3155)(最大密度子圖+最小割):點擊這里

總結

以上是生活随笔為你收集整理的分治 —— 01 分数规划的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。