题意:
给出一些货币和货币之间的兑换比率,问是否可以使某种货币经过一些列兑换之后,货币值增加。
举例说就是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\n");
else
printf("No\n");
}
}
最后写了一个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("\n");
}*/
if(edges[1][1]>1.0)
printf("Yes\n");
else
printf("No\n");
}
}
最后再用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\n");
else
printf("No\n");
}
}
【问题】:Folyd算法能处理包含负权边的图吗?
答案是可以的。Floyd-Warshall算法和Bellman-Ford算法一样,可以处理边是负数的情况。
---《挑战程序设计竞赛》 P.103
POJ 2240 - Arbitrage(bellman_ford & floyd)的更多相关文章
-
poj 2240 Arbitrage(Bellman_ford变形)
题目链接:http://poj.org/problem?id=2240 题目就是要通过还钱涨自己的本钱最后还能换回到自己原来的钱种. 就是判一下有没有负环那么就直接用bellman_ford来判断有没 ...
-
POJ 2240 Arbitrage(Floyed-Warshall算法)
题意:给出n种货币,m种兑换比率(一种货币兑换为另一种货币的比率),判断测试用例中套汇是否可行.(套汇的意思就是在经过一系列的货币兑换之后,是否可以获利.例如:货币i→货币j→货币i,这样兑换后,是否 ...
-
POJ 2240 Arbitrage(SPFA+邻接矩阵)
( ̄▽ ̄)" #include<iostream> #include<cstdio> #include<cmath> #include<algori ...
-
poj 2240 Arbitrage (Floyd)
链接:poj 2240 题意:首先给出N中货币,然后给出了这N种货币之间的兑换的兑换率. 如 USDollar 0.5 BritishPound 表示 :1 USDollar兑换成0.5 Britis ...
-
POJ 3259 Wormholes (Bellman_ford算法)
题目链接:http://poj.org/problem?id=3259 Wormholes Time Limit: 2000MS Memory Limit: 65536K Total Submis ...
-
POJ 2240 Arbitrage(floyd)
http://poj.org/problem?id=2240 题意 : 好吧,又是一个换钱的题:套利是利用货币汇率的差异进行的货币转换,例如用1美元购买0.5英镑,1英镑可以购买10法郎,一法郎可以购 ...
-
POJ 2240 Arbitrage(判正环)
http://poj.org/problem?id=2240 题意:货币兑换,判断最否是否能获利. 思路:又是货币兑换题,Belloman-ford和floyd算法都可以的. #include< ...
-
POJ 2240	 Arbitrage (求负环)
Arbitrage 题目链接: http://acm.hust.edu.cn/vjudge/contest/122685#problem/I Description Arbitrage is the ...
-
POJ 2240 Arbitrage (Bellman Ford判正环)
Arbitrage Time Limit: 1000MS Memory Limit: 65536K Total Submissions:27167 Accepted: 11440 Descri ...
随机推荐
-
python学习笔记(二)
(一)模块打包 ---> 注:suba和subb文件夹下的__init__.py文件,即使为空,也必须存在 "setup.py" from distut ...
-
VB发送后台按键和组合键
http://files.cnblogs.com/files/liuzhaoyzz/VB%E5%8F%91%E9%80%81%E5%90%8E%E5%8F%B0%E7%BB%84%E5%90%88%E ...
-
一些Layout的坑。坑死我自己了
iOS这个东西,初学感觉,还好还好,然后一年之后再来修复一下初学的时候的代码,我只是感觉头很晕- - 别扶我. AutoLayout的坑,明明以前都没有的!!!升了iOS10就突然发现了这个坑,其实也 ...
-
PagerAdapter 用法
PagerAdapter简介 PagerAdapter是android.support.v4包中的类,它的子类有FragmentPagerAdapter, FragmentStatePagerAdap ...
-
net-snmp配置:snmp v3的安全配置
net-snmp配置:snmp v3的安全配置 net-snmp配置:snmp v3的安全配置 增加snmp v3用户 增加 认证且加密只读账号(authPriv) 增加 认证且加密的读写账户 增加 ...
-
spring事件通知机制详解
优势 解耦 对同一种事件有多种处理方式 不干扰主线(main line) 起源 要讲spring的事件通知机制,就要先了解一下spring中的这些接口和抽象类: ApplicationEventPub ...
-
OCA读书笔记(14) - 备份和恢复基本概念
备份恢复概念 如何判断数据库的一致性 在mount状态下,oracle如何判断数据库的一致性 scn:system change number,它是数据库时钟 如何查询当前系统的scn: select ...
-
python的迭代器、生成器、装饰器
迭代器.生成器.装饰器 在这个实验里我们学习迭代器.生成器.装饰器有关知识. 知识点 迭代器 生成器 生成器表达式 闭包 装饰器 实验步骤 1. 迭代器 Python 迭代器(Iterators)对象 ...
-
Mybatis十( mybatis其他使用)
1.批量执行 public void addUser(User user); <insert id="addUser" parameterType="model.U ...
-
变换CALayer锚点实现模拟时钟的动画
变换CALayer锚点实现模拟时钟的动画 变换锚点得需要一点理论知识,看下图就能明白:). https://developer.apple.com/library/ios/documentation/ ...