• POJ 2240


    题意:

    给出一些货币和货币之间的兑换比率,问是否可以使某种货币经过一些列兑换之后,货币值增加。

    举例说就是1美元经过一些兑换之后,超过1美元。可以输出Yes,否则输出No。

    分析:

    首先我们要把货币之间的关系转化成一张图。转化时,用STL里面的map很方便。

    为每种货币分配一个序列号,一个序列号代表了一个图中间的NODE,而node之间的edge用汇率表示。

    一开始用Dijkstra算法做,死活AC不了,网友给的理由是:

    由于Dijkstra算法不能处理带有负权值的最短路,但此题中,两种货币之间的兑换比率可能小于1,相当于这条路径的权值为负

    前车之鉴,WA的代码:

    #include<iostream>
    #include<cstdio>
    #include<queue>
    #include<string.h>
    #include<string>
    #include<map>
    using namespace std;
    #define maxn 31
    #define inf 0x3f3f3f3f
    double edges[maxn][maxn];
    double dist[maxn];
    typedef pair<int,int> P;
    void init(){
    	for(int i=1;i<maxn;i++)
    		for(int j=1;j<maxn;j++)
    			edges[i][j]=(i==j?1:0);//1代表等价价换,0:代表无法交换
    }
    
    void dijkstra(int s,int n){
    	bool visited[maxn];
    	memset(visited,0,sizeof(visited));
    	visited[s]=true;
    	for(int i=1;i<=n;i++)
    		dist[i]=edges[s][i];
    	for(int i=1,u;i<=n;i++){
    		double max=-1;
    		for(int j=1;j<=n;j++)
    			if(!visited[j]&&dist[j]>max){
    				max=dist[j]; u=j;
    			}
    
    			visited[u]=true;
    			for(int j=1;j<=n;j++){
    				if(dist[u]*edges[u][j]>dist[j])
    					dist[j]=dist[u]*edges[u][j];
    			}
    	}
    }
    
    int main(){
    	//freopen("in.txt","r",stdin);
    	int n,cases=0;
    	while(scanf("%d",&n)!=EOF && n){
    		cases++;
    		init();
    		map<string,int> ma;
    		string s,t;
    		for(int i=1;i<=n;i++){
    			cin>>s;
    			ma.insert(make_pair(s,i));
    		}
    		int m;
    		double tmp;
    		scanf("%d",&m);
    		while(m--){
    			cin>>s>>tmp>>t;
    			edges[ma[s]][ma[t]]=tmp;
    		}
    
    		dijkstra(1,n);
    		printf("Case %d: ",cases);
    		if(dist[1]>1.0)
    			printf("Yes
    ");
    		else 
    			printf("No
    ");
    	}
    }

    最后写了一个Floyd的代码版本,结果一下子就过了,我只能默默的哭了

    #include<iostream>
     #include<cstdio>
     #include<queue>
     #include<string.h>
     #include<string>
     #include<map>
     using namespace std;
     #define maxn 31
     #define inf 0x3f3f3f3f
     double edges[maxn][maxn];
     void init(){
         for(int i=1;i<maxn;i++)
             for(int j=1;j<maxn;j++)
                 edges[i][j]=(i==j?1:0);//1:代表等价交换,0:代表无法交换
     }
     
     void floyd_warshall(int s,int n){
         for(int k=1;k<=n;k++){
             for(int i=1,u;i<=n;i++){
                 for(int j=1;j<=n;j++){
                     if(edges[i][k]*edges[k][j]>edges[i][j])//如果找到了更好的交换方案
                         edges[i][j]=edges[i][k]*edges[k][j];
                 }
             }
         }
     }
     
     int main(){
         //freopen("in.txt","r",stdin);
         int n,cases=0;
         while(scanf("%d",&n)!=EOF && n){
             cases++;
             init();
             map<string,int> ma;
             string s,t;
             for(int i=1;i<=n;i++){
                 cin>>s;
                 ma.insert(make_pair(s,i));
             }
             int m;
             double tmp;
             scanf("%d",&m);
             while(m--){
                 cin>>s>>tmp>>t;
                 edges[ma[s]][ma[t]]=tmp;
             }
     
             dijkstra(1,n);
             printf("Case %d: ",cases);
             /*for(int i=1,u;i<=n;i++){
                 for(int j=1;j<=n;j++){
                     printf("%.2f  ",edges[i][j]);
                 }
                 printf("
    ");
             }*/
             if(edges[1][1]>1.0)
                 printf("Yes
    ");
             else 
                 printf("No
    ");
         }
    }

    最后再用bellman_ford模板成功ac了一次。

     #include<iostream>
     #include<cstdio>
     #include<queue>
     #include<string.h>
     #include<string>
     #include<map>
     using namespace std;
     
     #define maxn 1000
     #define inf 0x3f3f3f3f    
     struct edge{
         int from;
         int to;
         float cost;
         edge(){
             from=0,to=0,cost=0;
         }
         edge(int a,int b ,float c){
             from=a,to=b,cost=c;
         }
     };
     edge Edges[maxn];
     float dist[maxn];
     void bellman_ford(int s,int V,int E){
         for(int i=1;i<=V;i++)
             dist[i]=0;
         dist[s]=1.0;
         for(int i=1;i<=V;i++){//这里可以改成while(true),但在有负权的情况下,会增加更多的循环,故建议照样例中写
             bool update=false;
             for(int j=1;j<=E;j++){
                 edge e=Edges[j];
                 if(dist[e.to]<dist[e.from]*e.cost){
                     dist[e.to]=dist[e.from]*e.cost;
                     update=true;
                 }
             }
             if(!update)break;//一旦在某次循环中,不能再更新当前dist,那么就能提前结束该算法,break之
         }
     }
     
     void init(int n){
         for(int i=1;i<=n;i++){
             for(int j=1;j<=n;j++){
                 if(i==j)   Edges[i]=edge(i,j,1.0);//初始化,1:等价交换
                 else       Edges[i]=edge(i,j,0);  //0:无法交换
             }
         }
     }
     
     
     int main(){
         //freopen("in.txt","r",stdin);
         int n,cases=0;
         while(scanf("%d",&n)!=EOF && n){
             cases++;
             init(n);
             map<string,int> ma;
             string s,t;
             for(int i=1;i<=n;i++){
                 cin>>s;
                 ma.insert(make_pair(s,i));   //构造字符串与数值的映射关系
             }
             int m;
             double tmp;
             scanf("%d",&m);
             for(int i=1;i<=m;i++){
                 cin>>s>>tmp>>t;
                 Edges[i]=edge(ma[s],ma[t],tmp);
             }
     
             bellman_ford(1,n,m);
             printf("Case %d: ",cases);
             if(dist[1]>1.0)
                 printf("Yes
    ");
             else 
                 printf("No
    ");
         }
     }

    【问题】:Folyd算法能处理包含负权边的图吗?

           答案是可以的。Floyd-Warshall算法和Bellman-Ford算法一样,可以处理边是负数的情况。

                                                                                                               ---《挑战程序设计竞赛》 P.103

  • 相关阅读:
    Android相关sdk使用
    Uniscribe文字自动换行
    Chrome RenderText分析(2)
    c++智能指针
    codepage IMLangCodePages
    GUI 快捷键的实现思路
    买车险
    九年---祝爱永存!
    算法
    Windows内核安全与驱动开发
  • 原文地址:https://www.cnblogs.com/ZJUT-jiangnan/p/3932844.html
Copyright © 2020-2023  润新知