Desert King POJ2728(Prim+迭代+0-1分数规划)

【原题地址】: POJ2728

【题目大意】:

选 \(n-1\) 条边,最小化这些边的\[\frac{\sum w_i} {\sum d_i}\]

其中 \(w_i\) 为第 \(i\) 条边的花费,\(d_i\) 为这条边所连接的两个点的距离。

\(w_i\) 为连接的两个点的 \(z\) 值差的绝对值, \(d_i\) 为欧几里得距离

【题解】:

这道题是0-1分数规划的经典题目

我们令\[\frac{\sum w_i} {\sum d_i}=k\]

这样二分 \(k\) 的值

将所有的边权改为 \(w_i - k*d_i\)

Prim 求出最小生成树

注: 这道题负边很多,用堆优化prim会超时

若最小生成树边权总和 \(≥ 0\),则说明 \(k\) 值小,否则 \(k\) 值偏大。

如果用二分可能会超时

我们设 \(MST(now)\) 为 \(k=now\) 时最小生成树的结果

那么可以发现当 \(now\) 越大则 \(MST(now)\) 值越小

所以我们采用迭代,用上次计算的值,计算当前值

【AC代码】:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
const int maxl=1e3+10;
int n;
int abs(int x)
{
    return x>0?x:-x;
}
double dis[maxl][maxl];
int x[maxl],y[maxl],z[maxl],cost[maxl][maxl];
int vis[maxl];
double to[maxl];
double tot_cost,tot_dis;
int reach[maxl];
void prim(double mid)
{
    vis[1]=1;
    for(int i=2;i<=n;i++)to[i]=cost[1][i]-dis[1][i]*mid,vis[i]=0,reach[i]=1;
    tot_cost=tot_dis=0;
    for(int i=1;i<=n-1;i++)
    {
        int pos;
        double minn=1e50;
        for(int j=2;j<=n;j++)
        if(!vis[j])
        {
            if(minn>to[j])
            {
                minn=to[j];
                pos=j;
            }
        }
        vis[pos]=1;
        tot_cost+=cost[reach[pos]][pos];
        tot_dis+=dis[reach[pos]][pos];
        for(int j=2;j<=n;j++)
        if(!vis[j]){
            if(to[j]>cost[pos][j]-dis[pos][j]*mid)to[j]=cost[pos][j]-dis[pos][j]*mid,reach[j]=pos;
        }
    }
}
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 i=1;i<=n;i++)
        for(int j=i;j<=n;j++)
        dis[i][j]=dis[j][i]=sqrt((x[i]*1.0-x[j])*(x[i]*1.0-x[j])+(y[i]*1.0-y[j])*(y[i]*1.0-y[j])),cost[i][j]=cost[j][i]=abs(z[i]-z[j]);
        double ans=0,last=1e100;
        while(abs(ans-last)>1e-4)
        {
            prim(ans);
            last=ans;
            ans=tot_cost/tot_dis;
        }
        printf("%.3f\n",ans);

    }
}

原文地址:https://www.cnblogs.com/Harry-bh/p/8798435.html

时间: 2024-07-30 12:29:57

Desert King POJ2728(Prim+迭代+0-1分数规划)的相关文章

poj 2728(Desert King) 最优比例生成树 (分数规划)

这题是最小生成树的一种扩展,就是求一棵树  使得 k =sigma(cost)/ sigma(len)  最小.   其中cost 为每条边花费,len为长度.  这实际上就是一个最优比例生成树.最优比例生成树的求解使用了分数规划的方法.  我们先任取k,假设k是最小值,那么sigma(ccost)-k*sigma(len)==0  .那么我们就新建图边权 为  ccosti-k*leni  .求一次最小生成树,如果生成树权值小于0,那么书名其实k还是有减小的空间的,否则,k不可能是最小.这样我

POJ 2728 Desert King (最优比率生成树---01分数规划)

题目地址:POJ 2728 01分数规划的应用之一-最优比率生成树. 跟普通的01分数规划类似,只是这题的验证函数改成了最小生成树来验证.弱用的迭代法. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #include <stdlib.h> #include <map>

POJ2728 最小比率生成树/0-1分数规划/二分/迭代(迭代不会)

用01分数规划 + prime + 二分 竟然2950MS惊险的过了QAQ 前提是在TLE了好几次下过的 = = 题目意思:有n个村庄,村庄在不同坐标和海拔,现在要对所有村庄供水,只要两个村庄之间有一条路即可,建造水管距离为坐标之间的欧几里德距离,费用为海拔之差,现在要求方案使得费用与距离的比值最小,很显然,这个题目是要求一棵最优比率生成树. 解题思路: 对答案进行二分,当把代进去的答案拿来算最小生成树的时候,一旦总路径长度为0,就是需要的答案. 0-1规划是啥? 概念有带权图G, 对于图中每条

bzoj 3232 圈地游戏——0/1分数规划(或网络流)

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3232 当然是0/1分数规划.但加的东西和减的东西不在一起,怎么办? 考虑把它们合在一起.因为边围成的形状像一个环,所以把格子的贡献也放到边上,然后正常判环. 放到边上的方法就是:比如竖着的边,可以在每一行上维护该行格子值前缀和,然后指定那个围成的形状是,比如,逆时针的,那么向上的边就加上到它为止的前缀值,向下的边就减去到它为止的前缀值,然后就能判环了! 这样一定只有一个环.但多个环答案不会

0/1分数规划

学习了lyd书上的0/1分数规划,发现这类题目都有一个特点,就是求$\frac{\sum_{a_{i}*x_{i}}}{\sum_{b_{i}*x_{i}}}$的最大或者最小,再加一些限制取不取的条件. POJ2976 二分答案+sort取前(n-k+1)个. #include <iostream> #include <cstdio> #include <algorithm> #include <cmath> using namespace std; con

POJ - 2976 Dropping tests &amp;&amp; 0/1 分数规划

POJ - 2976 Dropping tests 你有 \(n\) 次考试成绩, 定义考试平均成绩为 \[\frac{\sum_{i = 1}^{n} a_{i}}{\sum_{i = 1}^{n} b_{i}}\] 你可以考虑放弃 \(K\) 次成绩, 求最大平均成绩 * 100 小插曲: 被精度卡成喜羊羊 0/1分数规划\(from\)人生导师 Solution 01分数规划(不是很)裸题, 在每次 \(check\) 时, 选取较大的 \(num - K + 1\) 次即可 Code #

2019.4.9 一题——概率期望+0/1分数规划+最大权闭合子图

没注意 “第 x 条边和第 y 条边的起点是相同的” 的限制.没想出来. 有这个限制,可以考虑每个点分别计算.令 \( f[i] \) 表示从 i 出发的最大边数期望,那么先把拓扑序在自己之后的点的 \( f[ ] \) 算出来,然后考虑自己这个点的出边怎么做能使自己的 \( f[ ] \) 最大. \( f[i]=\frac{ \sum f[j]+1 }{ d } \) ,其中 d 是保留下来的边数, j 是保留边指向的点. 如果把 \( f[ ]+1 \) 看做收益, 1 看做代价,那么这个

『0/1分数规划 二分法』

0/1分数规划 模型 0/1分数规划指的是这样一个问题模型: 给定整数\(a_1,a_2,...,a_n\)和\(b_1,b_2,...,b_n\),求一组解\(x_1,x_2,...,x_n(\forall\ i\in[1,n],x_i=1,0)\),使得下式最大化:\[\frac{\sum_{i=1}^na_i*x_i}{\sum_{i=1}^nb_i*x_i}\] 简单地说,就是给定\(n\)对整数\(a_i,b_i\),从中选取若干对,使得选出的\(a\)之和与\(b\)之和的比值最大.

[例题/总结]0/1分数规划

[TOC] ##一.总述 0/1分数规划是专门解决0/1分数规划模型的一种算法~~(废话)~~.所以说0/1分数规划模型是什么呢?给定整数{\(a_1,a_2,a_3,...,a_n\)},{\(b_1,b_2,b_3,...,b_n\)}从中选出若干对数,使得它们各自和的比值最大.公式如下: \(\frac{\sum_{p=1}^{n}a_p\times x_p}{\sum_{p=1}^{n}b_p\times x_p}(x_p=1,0)\) ##二.实现原理 那么我们用什么方法可以求出这样一