POJ3111 Dinkelbach算法

假定一個答案ans,根據這個答案,計算

s_i.s=a_i-ans*b_i

s_i.idx=i

根據s_i.s排序,此時我們並不是把最大的ks_i.s相加跟0比較,而是把s_i.s最大的k個的

                                         \large up=\sum_{i=1}^{k} \ a_{s_i.idx}                         \large down=\sum_{i=1}^{k} \ b_{s_i.idx}

                                                                       \large tmp=\frac{up}{down}

如果

                                                                              \large ans==tmp

結束循環,否則

                                                                               \large ans=tmp

繼續循環。

逐漸逼近最優解的過程。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
typedef double db;
const int N=1e5+5;
const db eps=1e-8;
db v[N],w[N];
struct node
{
    db s;
    int idx;
    bool operator < (const node B) const{return s<B.s;}
}s[N];
int main()
{
    int n,k;
    db ans,tmp;
    while(~scanf("%d%d",&n,&k))
    {
        for(int i=1;i<=n;i++) scanf("%lf%lf",&v[i],&w[i]);
        ans=1e7;
        tmp=0;
        while(fabs(tmp-ans)>eps)
        {
            ans=tmp;
            for(int i=1;i<=n;i++) 
            {
                s[i].s=v[i]-ans*w[i];
                s[i].idx=i;
            }
            sort(s+1,s+n+1);
            db up=0,down=0;
            for(int i=n;i>n-k;i--) up+=v[s[i].idx],down+=w[s[i].idx];
            tmp=up/down;
        }
        for(int i=n;i>n-k;i--) printf("%d ",s[i].idx);
    }
}

 

發佈了74 篇原創文章 · 獲贊 4 · 訪問量 5045
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章