zoukankan      html  css  js  c++  java
  • 分数规划

    普通01分数规划

    由n个物品,每个物品由两个属性a和b,选出k个物品,使Σai / Σbi 的值最大

    设x=Σai / Σbi, F()=Σa-xΣb, D()=a-xb

    当F()=0时,则为答案;当F()>0时,则说明答案小了;当F()<0时,则说明答案大了

    二分答案

    double l=0,r=1.0,mid;
    while(r-l>1e-5) {
        mid=(l+r)/2;
        if(work(mid)) l=mid;
        else r=mid;
    }
    int work(double x) {
        for(int i=0;i<n;i++) d[i]=a[i]-x*b[i];
        sort(d,d+n);
        double F=0;
        for(int i=n-1;i>=n-k;i--) F+=d[i];
        return F>=0;
    }

    最优比率生成树

    带权无向图G,对于每条边有vali,costi。现在求一棵生成树T,最大(小)化val / cost。

    二分答案,对边赋值w=val-r*cost,有选前|G|-1条大的w,即求最大生成树,套用01分数规划的模板。

    例题:http://poj.org/problem?id=2728 

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    using namespace std;
    #define maxn 1050
    #define inf 0x7fffffff
    static double eps=1e-4;
    int vis[maxn],x[maxn],y[maxn],z[maxn],p[maxn];
    double d[maxn],cost[maxn][maxn],dis[maxn][maxn];
    int n;
    double prim(double x) {
        double totcost=0,totdis=0;
        double sum=0.0;
        for(int i=1;i<=n;i++) p[i]=1;
        d[1]=0;
        memset(vis,0,sizeof(vis)); vis[1]=1;
        for(int i=2;i<=n;i++) d[i]=cost[1][i]-dis[1][i]*x;
    
        int k;
        for(int i=2;i<=n;i++) {
            double mincost=inf;
            for(int j=2;j<=n;j++) {
                if(!vis[j] && d[j]<mincost) {
                    mincost=d[j];
                    k=j;
                }
            }
            vis[k]=1;
            sum+=mincost;
            totcost+=cost[p[k]][k];
            totdis+=dis[p[k]][k];
            for(int j=1;j<=n;j++) {
                if(!vis[j] && d[j]>cost[k][j]-dis[k][j]*x) {
                    d[j]=cost[k][j]-dis[k][j]*x;
                    p[j]=k;
                }
            }
        }
    //    return totcost/totdis; ///二分
        return sum; ///迭代
    }
    int main( ) {
        while(scanf("%d",&n),n) {
            for(int i=1;i<=n;i++) {
                scanf("%d%d%d",&x[i],&y[i],&z[i]);
                for(int j=1;j<i;j++) {
                    double tmp=(x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]);
                    cost[i][j]=cost[j][i]=abs(z[i]-z[j]);
                    dis[i][j]=dis[j][i]=sqrt(tmp);
                }
            }
            double a=0;
    //        while(1) {
    //            double b=prim(a);
    //            if(abs(a-b)<eps) {
    //                printf("%.3f
    ", a);
    //                break;
    //            }
    //            else a=b;
    //        }
            ///迭代
            double head=0,tail=100000.0;
            while(tail-head>1e-5) {
                double mid=(head+tail)/2.0;
                a=prim(mid);
                if(a>=0) head=mid;
                else tail=mid;
            }
            printf("%.3f
    ", tail);
        }
        return 0;
    }
    View Code

    最优比率生成环

    给定有点权和边权的图,求一个环,使得环的点权和与边权和的比值最大。

    01分数规划+树形背包

  • 相关阅读:
    把EXE可执行文件等作为资源包含在Delphi编译文件中
    delphi怎么做桌面滚动文字?
    cxGrid控件过滤筛选后如何获更新筛选后的数据集
    我的ecshop二次开发经验分享
    ECSHOP 数据库结构说明 (适用版本v2.7.3)
    cxGrid 怎样才能让不自动换行 WordWrap:=false
    vi notes
    ODI中显示us7ascii字符集的测试
    ODI 11g & 12c中缓慢变化维(SCD)的处理机制
    ODI中的临时接口
  • 原文地址:https://www.cnblogs.com/iwomeng/p/11618759.html
Copyright © 2011-2022 走看看