HDU 3696&& FZU 2006 -- Farm Game

本文介绍了一种利用最短路径算法解决产品转化过程中收益最大化的问题。通过将问题转化为图上的最长路径问题,并借助SPFA算法,实现产品间转化效益的最大化。文章详细解释了如何使用对数变换来简化计算过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:  给出每个种类产品的数量和单价, 以及他们之间单向的转化关系。询问最大利益

思路:   将每个种类 通过转化关系后的最大单价求出,去乘数量,求和。

转化率是个小数,通过乘法关系会失去精度,取log 变为+法、 网上都是这么说的。。。。

但是我觉得取log 是因为把乘法变为加法后,目的是为了变为最短路spfa的加减法的模型,否则如果是乘除法的关系,无法跑最短路。

在跑最短路的时候 建立一个超级原点,求这个原地到每个种类的距离(最大单价)。 也就是一个最长路模型


#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <queue>
#include <vector>
#include <cmath>
#include <stack>

using namespace std;
const int maxn=100005;
typedef long long ll;
vector<pair<int ,double > > vec[maxn];
int vis[maxn];
double p[maxn],w[maxn];
double dis[maxn];
int n,m;

int spfa(int st)
{
    for(int i=0;i<=n;i++)
    {
        vis[i]=0,dis[i]=0;
    }
    vis[st]=1,dis[st]=0;
    deque<int>q;
    q.push_front(st);
    int u;
    while(!q.empty())
    {
        u=q.front();
        q.pop_front();
        vis[u]=0;
        for(int i=0; i<vec[u].size(); i++)
        {

            int v=vec[u][i].first;
            double w=vec[u][i].second;
            if( dis[v] < w+dis[u] )
            {
                dis[v]=w+dis[u];
                if(!vis[v])
                {
                    vis[v]=1;
                    if(!q.empty()&&dis[v]<dis[q.front()])
                        q.push_back(v);
                    else
                        q.push_front(v);
                }
            }
        }
    }
    return 1;
}

int main()
{
    while(~scanf("%d",&n ),n )
    {

    for(int i=0; i<maxn; i++)
        vec[i].clear();
    for(int i=1; i<=n; i++)
    {
        scanf("%lf%lf",&p[i],&w[i]);
        vec[0].push_back(make_pair(i,log10(p[i])));
    }
    scanf("%d",&m);
    for(int i=1;i<=m;i++)
    {
        int k,a,b;
        scanf("%d%d",&k,&a);
        k--;
        double px;
        while(k--)
        {
            scanf("%lf%d",&px,&b);
            px=log10(px);
            vec[b].push_back(make_pair(a,px));
            a=b;

        }
    }
    spfa(0);
    double ans=0;
    for(int i=1;i<=n;i++)
    {
        if(p[i]<pow(10.0,dis[i]))
            p[i]=pow(10.0,dis[i]);
        ans+=p[i]*w[i];
    }
    printf("%.2lf\n",ans);

    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值