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

    题目背景

    题目描述

    在n个人中,某些人的银行账号之间可以互相转账。这些人之间转账的手续费各不相同。给定这些人之间转账时需要从转账金额里扣除百分之几的手续费,请问A最少需要多少钱使得转账后B收到100元。

    输入输出格式

    输入格式:

    第一行输入两个正整数n,m,分别表示总人数和可以互相转账的人的对数。

    以下m行每行输入三个正整数x,y,z,表示标号为x的人和标号为y的人之间互相转账需要扣除z%的手续费 (z<100)。

    最后一行输入两个正整数A,B。数据保证A与B之间可以直接或间接地转账。

    输出格式:

    输出A使得B到账100元最少需要的总费用。精确到小数点后8位。

    输入输出样例

    输入样例#1:
    3 3                                     
    1 2 1
    2 3 2
    1 3 3
    1 3
    
    输出样例#1:
    103.07153164

    说明

    1<=n<=2000

    AC代码:

    N^2都能过,无语。。

     1 #include<iostream>
     2 #include<cstdio>
     3 #define MAXN 2001
     4 #define inf 99999
     5 using namespace std;
     6 int N,M,A,B;
     7 double m[MAXN][MAXN];
     8 int main()
     9 {
    10     int i,j;
    11     cin>>N>>M;
    12     cout.setf(ios::fixed);
    13     for (i=0;i<N;i++)
    14         for (j=0;j<N;j++)
    15             m[i][j]=1/inf;// 就这样来看是0
    16     
    17     for (i=0;i<M;i++)
    18     {
    19         int x,y,t;
    20         cin>>x>>y>>t;
    21         x--; y--;
    22         m[x][y]=m[y][x]=1-(t/100.0);//转换成剩余百分之多少
    23     }
    24    
    25     cin>>A>>B;
    26     A--; B--;
    27     //dijkstra
    28     double dis[MAXN];                            //dis i:money needed to trans 100 to i
    29     bool book[MAXN];
    30     book[B]=true;
    31     for (i=0;i<N;i++)
    32     {
    33         dis[i]=100/m[B][i];                    //init dis[]
    34         book[i]=false;                            //init book[]
    35     }
    36     for (j=0;j<N;j++)
    37     {
    38         int nmin;
    39         double min=inf;
    40         for (i=0;i<N;i++)
    41             if (dis[i]<min&&!book[i])
    42             {
    43                 nmin=i;
    44                 min=dis[nmin];                    //find #min->nmin
    45             }
    46         book[nmin]=true;                        //record in book[]
    47         for (i=0;i<N;i++)
    48             if (min/m[nmin][i]<dis[i]&&!book[i])        //relax
    49                 dis[i]=min/m[nmin][i];
    50     }
    51     printf("%.8lf",dis[A]);
    52     return 0;
    53 }

    80分代码存档:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<queue>
     5 #define N 2005
     6 using namespace std;
     7 int n,m,S,E,head[N],ei;
     8 double dis[N];
     9 bool exist[N];
    10 struct node{
    11     int u,v,next;
    12     double w;
    13 }e[N*25];
    14 void add_edge(int u,int v,int x){
    15     double w=(double)x;w/=100;
    16     e[++ei].u=u;e[ei].v=v;e[ei].w=w;
    17     e[ei].next=head[u];head[u]=ei;
    18 }
    19 queue<int> q;
    20 void SPFA(){
    21     for(int i=1;i<=n;i++) dis[i]=99999999.0;
    22     memset(exist,false,sizeof(exist));
    23     exist[S]=true;q.push(S);dis[S]=100.0;
    24     while(!q.empty()){
    25         int p=q.front();q.pop();
    26         exist[p]=false;
    27         for(int i=head[p];i;i=e[i].next){
    28             int v=e[i].v;
    29             if(dis[v]>dis[p]/(e[i].w)){
    30                 dis[v]=dis[p]/(e[i].w);
    31                 if(!exist[v]){
    32                     q.push(v);exist[v]=true;
    33                 }
    34             }
    35         }
    36     }
    37 }
    38 int main()
    39 {
    40     scanf("%d%d",&n,&m);
    41     for(int i=1,u,v,w;i<=m;i++){
    42         scanf("%d%d%d",&u,&v,&w);
    43         add_edge(v,u,100-w);
    44         add_edge(u,v,100-w);
    45     }
    46     scanf("%d%d",&E,&S);
    47     SPFA();
    48     printf("%.8lf",dis[E]);
    49     return 0;
    50 }

    刚开始用100往回乘(1+e[i].w)全错了,后来改成除了。。

    思路:建立无向图(刚开始建成有向图了。。),跑最短路。。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<queue>
     5 using namespace std;
     6 int n,m,S,E,head[15000],ei;
     7 double dis[2100];
     8 bool exist[2010];
     9 struct node{
    10     int u,v,next;
    11     double w;
    12 }e[20000];
    13 void add_edge(int u,int v,int x){
    14     double w=(double)x;w/=100.0;
    15     e[++ei].u=u;e[ei].v=v;e[ei].w=w;
    16     e[ei].next=head[u];head[u]=ei;
    17 }
    18 queue<int> q;
    19 void SPFA(){
    20     for(int i=1;i<=n;i++) dis[i]=99999999.0;
    21     memset(exist,false,sizeof(exist));
    22     exist[S]=true;q.push(S);dis[S]=100.0;
    23     while(!q.empty()){
    24         int p=q.front();q.pop();
    25         exist[p]=false;
    26         for(int i=head[p];i;i=e[i].next){
    27             int v=e[i].v;
    28             if(dis[v]>dis[p]*(1.0+e[i].w)){
    29                 dis[v]=dis[p]*(1.0+e[i].w);
    30                 if(!exist[v]){
    31                     q.push(v);exist[v]=true;
    32                 }
    33             }
    34         }
    35     }
    36 }
    37 int main()
    38 {
    39     scanf("%d%d",&n,&m);
    40     for(int i=1,u,v,w;i<=m;i++){
    41         scanf("%d%d%d",&u,&v,&w);
    42         add_edge(v,u,w);
    43         add_edge(u,v,w);
    44     }
    45     scanf("%d%d",&E,&S);
    46     SPFA();
    47     printf("%.8lf",dis[E]);
    48     return 0;
    49 }

    这样写不知道为什么结果总是整数部分正确,小数部分全是0,一时没看出哪里错了

  • 相关阅读:
    #Leetcode# 876. Middle of the Linked List
    #Leetcode# 237. Delete Node in a Linked List
    #Leetcode# 234. Palindrome Linked List
    #Leetcode# 149. Max Points on a Line
    #Leetcode# 152. Maximum Product Subarray
    #Leetcode# 228. Summary Ranges
    #Leetcode# 227. Basic Calculator II
    PAT 1089 狼人杀-简单版
    linux——web安全之sql注入【预习阶段】
    linux——攻防技术介绍|主动攻击|被动攻击
  • 原文地址:https://www.cnblogs.com/suishiguang/p/6227587.html
Copyright © 2011-2022 走看看