汇率倒卖,看是否存在获利可能。
考察的是有权重的有向图的单源最短路径,权重上有微小的变形,只要改变一点更新节点时的算法即可。
用的是bellman-ford算法,用floyd算法也可以,不过是单源最短路径这一章的习题,所以就用bellman-ford做了。
这道题是《 introduction to algorithms》2nd Edition 中 Chapter 24 single-source shortest paths这一张的习题,基本上是原题的第一问,第二问是要给出可获利倒卖顺序,这样就要为每种货币加一个父节点,然后递归调用输出货币名。程序也附在后面。
//2008-01-09 17:50:28 Accepted 1092 C++ 00:00.13 404K ////《introduction to algorithms》Problem 24-3.a #include<stdio.h> #include<string.h> struct MONEY{ char name[50];//货币名 float d; }; struct MONEY m[31];//每种货币的信息 float r[31][31];//汇率表 int nkind; int getno(char name[50])//get no by name { int i; for(i=1;i<=nkind;i++) { if(strcmp(m[i].name,name)==0) return i; } } void init(int s) { int i; for(i=1;i<=nkind;i++) m[i].d = 0.00; m[s].d = 1.00; } bool bford(int s) { init(s); int i,j,k; float t; for(k=1;k<=nkind;k++) { for(i=1;i<=nkind;i++) { for(j=1;j<=nkind;j++) { if(r[i][j]>0) { t=m[i].d*r[i][j]; if(m[j].d<t) m[j].d = t; } } } } if(m[s].d>1) return true; else return false; } int main() { freopen("1092.txt","r",stdin); int i,j,t,count=0; char str1[50],str2[50]; float exc; bool re; while((scanf("%d",&nkind)!=EOF) && nkind!=0) { count++; for(i=1;i<=nkind;i++) { scanf("%s",m[i].name); } for(i=0;i<31;i++)//初始化汇率表 { for(j=0;j<31;j++) r[i][j] = -1.00; } scanf("%d",&t); for(i=0;i<t;i++) { scanf("%s %f %s",str1,&exc,str2); r[getno(str1)][getno(str2)] = exc; } re=false; for(i=1;i<=nkind;i++) { if(bford(i)) { re = true; break; } } printf("Case %d: ",count); if(re) printf("Yes/n"); else printf("No/n"); } fclose(stdin); return 0; }
===========华丽的程序间的分隔线===========
//《introduction to algorithms》Problem 24-3.b #include<stdio.h> #include<string.h> struct MONEY{ char name[50];//货币名 float d; MONEY* pi; }; struct MONEY m[31];//每种货币的信息 float r[31][31];//汇率表 int nkind; void printpath(MONEY* s,MONEY* v) { if(v->pi!=s) { printpath(s,v->pi); printf(" %s",v->name); } else printf(" %s",v->name); } int getno(char name[50])//get no by name { int i; for(i=1;i<=nkind;i++) { if(strcmp(m[i].name,name)==0) return i; } } void init(int s) { int i; for(i=1;i<=nkind;i++) { m[i].d = 0.00; m[i].pi = NULL; } m[s].d = 1.00; } bool bford(int s) { init(s); int i,j,k; float t; for(k=1;k<=nkind;k++) { for(i=1;i<=nkind;i++) { for(j=1;j<=nkind;j++) { if(r[i][j]>0) { t=m[i].d*r[i][j]; if(m[j].d<t) { m[j].d = t; m[j].pi = &m[i]; } } } } } if(m[s].d>1) return true; else return false; } int main() { freopen("1092.txt","r",stdin); int i,j,t,count=0; char str1[50],str2[50]; float exc; bool re; while((scanf("%d",&nkind)!=EOF) && nkind!=0) { count++; for(i=1;i<=nkind;i++) { scanf("%s",m[i].name); } for(i=0;i<31;i++)//初始化汇率表 { for(j=0;j<31;j++) r[i][j] = -1.00; } scanf("%d",&t); for(i=0;i<t;i++) { scanf("%s %f %s",str1,&exc,str2); r[getno(str1)][getno(str2)] = exc; } re=false; for(i=1;i<=nkind;i++) { if(bford(i)) { re = true; break; } } printf("Case %d: ",count); if(re) { printf("Yes/n%s",m[i].name); printpath(&m[i],&m[i]); printf("/n"); } else printf("No/n"); } fclose(stdin); return 0; }