zoukankan      html  css  js  c++  java
  • 最小花费

    1111: 最小花费
    时间限制: 1 Sec  内存限制: 128 MB
    提交: 95  解决: 12
    [提交] [状态] [讨论版] [命题人:test]
    题目描述
    在n个人中,某些人的银行账号之间可以互相转账。这些人之间转账的手续费各不相同。给定这些人之间转账时需要从转账金额里扣除百分之几的手续费,请问A最少需要多少钱使得转账后B收到100元。 
    输入
    输入包含多组测试用例。 
    对于每组样例,第一行输入两个正整数n,m,分别表示总人数和可以互相转账的人的对数。(0<n<=2000)以下m行每行输入三个正整数x,y,z。表示标号为x的人和标号为y的人之间互相转账需要扣除z%的手续费(z<100)。 
    最后一行输入两个正整数A,B。数据保证A与B之间可以直接或间接地转账 
    输出
    输出A使得B到账100元最少需要的总费用。精确到小数点后8位。 
    样例输入
    3 3
    1 2 1
    2 3 2
    1 3 3
    1 3
    样例输出
    103.07153164
    #include <bits/stdc++.h>
    using namespace std;
    #define ll long long 
    #define N 2100
    #define inf 100000000
    int n,m;
    int g[N][N],d[N],pre[N];
    int num[N];
    bool vis[N];
    int  st,ed; 
    void init()
    {
         
        for(int i =0;i<N;i++) {
            for(int  j =0;j<N;j++)
            {
                if(i==j) g[i][j] =0;
                else g[i][j] = inf;
            }
            vis[i] = 0;d[i] =inf;pre[i]  =-1;
            num[i]  = 0;
        }
    }
    int x,y,z;
    void dijk(int  st){
         
        d[st]  =0;num[st]  =1;
        int min_num,minn;
        for(int i =0;i<n-1;i++)
        {
            minn=inf;
            for(int  j =1;j<=n;j++){
                if(!vis[j]&&d[j]<minn){
                    minn=d[j];
                    min_num=j;
                }
            }
                vis[min_num]  =1;
                for(int k =1;k<=n;k++){
                    if(!vis[k]){
                     
                    if(d[k]>d[min_num]+g[min_num][k]){
                        d[k]=d[min_num]+g[min_num][k];
                        pre[k] =min_num;
                        num[k]  =num[min_num]+1;
                    }
                else    if(d[k]==d[min_num]+g[min_num][k]){
                        if(num[k]<num[min_num]+1){//肯定是在相同路径长度下,走的路径边数越多越优 
                          num[k]  =num[min_num]+1;  
                        pre[k] =min_num;
                         
                    }
                    }
                }
        }
    }
    }
    x*(1-z1%)(1-z2%)...==100
    x=100/(1-z1%)(1-z2%)...//分母要最大,求最短路径 
    //相同路径长度下,走的路径边数越多越优 
    int main()
    {
        while(~scanf("%d%d",&n,&m))
        {
            init();
            for(int i =0;i<m;i++){
                scanf("%d%d%d",&x,&y,&z);
                g[x][y]=g[y][x]=z;
            }
            scanf("%d%d",&st,&ed);
            dijk(st);
            double ret= 100.0;
        for(int j =ed;pre[j]!=-1;j=pre[j]) 
        {
         //printf("%d ",j);
         double x = g[j][pre[j]]*1.0;
         //cout<<x<<endl;
         ret/=(1-x*0.01);
         //cout<<ret<<endl;
        }
        printf("%.8f
    ",ret);
        }
        return 0;
     }
  • 相关阅读:
    DP专集
    FJUT ACM 1212 集训队的药药切克闹
    Codecraft-18 and Codeforces Round #458 (Div. 1 + Div. 2, combined) C. Travelling Salesman and Special Numbers (组合数学)
    牛客网 Wannafly挑战赛8 C-小C打比赛 (状压DP)
    HDU 1260 TICKETS (简单DP)
    汇编入门学习笔记 段内转移和段间转移
    汇编入门学习笔记 循环程序设计
    汇编入门学习笔记 分支程序举例
    汇编入门学习笔记 16X+Y
    POJ
  • 原文地址:https://www.cnblogs.com/tingtin/p/11405310.html
Copyright © 2011-2022 走看看