POJ1860-Currency Exchange
2011-07-29 23:47
357 查看
转载请注明出处:優YoU http://user.qzone.qq.com/289065406/blog/1299337940
提示:关键在于反向利用Bellman-Ford算法
题目大意[/b]
有多种汇币,汇币之间可以交换,这需要手续费,当你用100A币交换B币时,A到B的汇率是29.75,手续费是0.39,那么你可以得到(100 - 0.39) * 29.75 = 2963.3975 B币。问s币的金额经过交换最终得到的s币金额数能否增加
货币的交换是可以重复多次的,所以我们需要找出是否存在正权回路,且最后得到的s金额是增加的
怎么找正权回路呢?(正权回路:在这一回路上,顶点的权值能不断增加即能一直进行松弛)
题目分析:[/b]
一种货币就是图上的一个点
一个“兑换点”就是图上两种货币之间的一个兑换环,相当于“兑换方式”M的个数,是双边
唯一值得注意的是权值,当拥有货币A的数量为V时,A到A的权值为K,即没有兑换
而A到B的权值为(V-Cab)*Rab
本题是“求最大路径”,之所以被归类为“求最小路径”是因为本题题恰恰与bellman-Ford算法的松弛条件相反,求的是能无限松弛的最大正权路径,但是依然能够利用bellman-Ford的思想去解题。
因此初始化d(S)=V 而源点到其他店的距离(权值)初始化为无穷小(0),当s到其他某点的距离能不断变大时,说明存在最大路径
提示:关键在于反向利用Bellman-Ford算法
题目大意[/b]
有多种汇币,汇币之间可以交换,这需要手续费,当你用100A币交换B币时,A到B的汇率是29.75,手续费是0.39,那么你可以得到(100 - 0.39) * 29.75 = 2963.3975 B币。问s币的金额经过交换最终得到的s币金额数能否增加
货币的交换是可以重复多次的,所以我们需要找出是否存在正权回路,且最后得到的s金额是增加的
怎么找正权回路呢?(正权回路:在这一回路上,顶点的权值能不断增加即能一直进行松弛)
题目分析:[/b]
一种货币就是图上的一个点
一个“兑换点”就是图上两种货币之间的一个兑换环,相当于“兑换方式”M的个数,是双边
唯一值得注意的是权值,当拥有货币A的数量为V时,A到A的权值为K,即没有兑换
而A到B的权值为(V-Cab)*Rab
本题是“求最大路径”,之所以被归类为“求最小路径”是因为本题题恰恰与bellman-Ford算法的松弛条件相反,求的是能无限松弛的最大正权路径,但是依然能够利用bellman-Ford的思想去解题。
因此初始化d(S)=V 而源点到其他店的距离(权值)初始化为无穷小(0),当s到其他某点的距离能不断变大时,说明存在最大路径
//Memory Time //252K 16MS #include<iostream> using namespace std; int n; //货币种数 int m; //兑换点数量 int s; //持有第s种货币 double v; //持有的s货币的本金 int all; //边总数 double dis[101]; //s到各点的权值 class exchange_points { public: int a; //货币a int b; //货币b double r; //rate double c; //手续费 }exc[202]; bool bellman(void) { memset(dis,0,sizeof(dis)); //这里与bellman的目的刚好相反。初始化为源点到各点距离无穷小 dis[s]=v; //即bellman本用于找负环,求最小路径,本题是利用同样的思想找正环,求最大路径 /*relax*/ bool flag; for(int i=1;i<=n-1;i++) { flag=false; for(int j=0;j<all;j++) if(dis[exc[j].b] < (dis[exc[j].a] - exc[j].c) * exc[j].r) //寻找最长路径 { //进行比较的是"某点到自身的权值"和"某点到另一点的权值" dis[exc[j].b] = (dis[exc[j].a] - exc[j].c) * exc[j].r; flag=true; } if(!flag) break; } /*Search Positive Circle*/ for(int k=0;k<all;k++) if(dis[exc[k].b] < (dis[exc[k].a] - exc[k].c) * exc[k].r) //正环能够无限松弛 return true; return false; } int main(void) { int a,b; double rab,cab,rba,cba; //临时变量 while(cin>>n>>m>>s>>v) { all=0; //注意初始化 for(int i=0;i<m;i++) { cin>>a>>b>>rab>>cab>>rba>>cba; exc[all].a=a; exc[all].b=b; exc[all].r=rab; exc[all++].c=cab; exc[all].a=b; exc[all].b=a; exc[all].r=rba; exc[all++].c=cba; } /*Bellman-form Algorithm*/ if(bellman()) cout<<"YES"<<endl; else cout<<"NO"<<endl; } return 0; }
相关文章推荐
- POJ1860——Currency Exchange
- poj 1860 最短路径变形
- poj 1860 Currency Exchange :bellman-ford
- poj1860
- poj1860(图论,bellman-ford)
- poj1860 Currency Exchange (bellman_ford)
- POJ 1860 (反向bellman用法)
- POJ 1860-Currency Exchange(最短路-回路套汇)
- POJ1860--Currency Exchange(最短路Bellman_Ford)
- POJ 1860 Currency Exchange(Ballman)
- POJ-1860 Currency Exchange
- poj 1860
- POJ-1860(Bellman()重要应用)
- POJ 1860 Currency Exchange (Bellman-Ford算法的运用)
- POJ 1860 Currency Exchange(求环变形)
- POJ 1860 Currency Exchange bellman_ford
- POJ 1860
- POJ1860 Currency Exchange 最短路bellman-ford
- POJ1860-Currency Exchange(bellman-ford求正环)
- poj1860 Currency Exchange floyd判断正环 (手动翻译)