Hdu 3696 Farm Game(最长路)

58 篇文章 0 订阅
17 篇文章 0 订阅
题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=3696

思路:每种商品可以直接卖掉,也可以换购后卖掉。所以设点n+1,从该点向每个商品连边权值为log(p[i])(将乘法转换为加法,直接使用SPFA)表示直接卖掉的单位价值;对于可以换购的商品 i-->j,连 j--> i 权值为log(b[j])的边(反向建图,只需求一次最长路),表示单位 i 商品可以转换为b[j] 的 j 商品(求最长路时逐步累乘转换率)。求n+1点到各点的最长路,dist[i]即为单位i商品的最大价值,与 i 商品的数量相乘累加即可。

#include<cstdio>
#include<vector>
#include<queue>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#define debu
using namespace std;
const int INF=0x3f3f3f3f;
const int maxn=1e4+50;
struct Node
{
    int v;
    double w;
    Node(int v=0,double w=0):v(v),w(w) {}
};
queue<int> q;
vector<Node> g[maxn];
double dist[maxn],b[maxn];
int v[maxn],n,m,k,a[maxn];
double val[maxn],have[maxn];
void solve(int s)
{
    memset(v,0,sizeof(v));
    while(!q.empty()) q.pop();
    for(int i=0; i<=n+1; i++) dist[i]=-INF;
    q.push(s),v[s]=0,dist[s]=0;
    while(!q.empty())
    {
        int now=q.front();
        q.pop(),v[now]=0;
        for(int i=0; i<g[now].size(); i++)
        {
            int nt=g[now][i].v;
            if(dist[nt]<dist[now]+g[now][i].w)
            {
                dist[nt]=dist[now]+g[now][i].w;
                if(!v[nt])
                {
                    v[nt]=1;
                    q.push(nt);
                }
            }
        }
    }
}
int main()
{
#ifdef debug
    freopen("in.in","r",stdin);
#endif // debug
    while(scanf("%d",&n)==1&&n)
    {
        for(int i=1; i<=n+1; i++) g[i].clear();
        for(int i=1; i<=n; i++)
        {
            scanf("%lf%lf",&val[i],&have[i]);
            g[n+1].push_back(Node(i,log10(val[i])));
        }
        scanf("%d",&m);
        for(int i=1; i<=m; i++)
        {
            scanf("%d",&k);
            scanf("%d",&a[0]);
            for(int j=1; j<=k-1; j++)
                scanf("%lf%d",&b[j],&a[j]);
            for(int j=1; j<=k-1; j++)
            {
                //cout<<a[j]<<" "<<a[j-1]<<" "<<b[j]*val[a[j]]<<endl;
                g[a[j]].push_back(Node(a[j-1],log10(b[j])));
            }
        }
        /*for(int i=1;i<=n+1;i++)
        {
            for(int j=0;j<g[i].size();j++)
                cout<<i<<" "<<g[i][j].v<<" "<<g[i][j].w<<endl;
        }*/
        solve(n+1);
        double ans=0.0;
        for(int i=1; i<=n; i++)
        {
            //cout<<dist[i]<<" "<<have[i]<<endl;
            ans+=pow(10.0,dist[i])*have[i];
        }
        printf("%.2f\n",ans);
    }
    return 0;
}







  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值