START
emmmm,做法和其他几个题解应该差不多,但是我觉得解释可以再多一点。
那么废话不多说。
这道题的要求比较简单,只是要求最后转换成原来的那种货币时获利大于0.01(1%),而且转换次数不超过n次(越少越好),然后输出最短次数的路径。
注意!!!!!:题目并没有要求是最大获利,只要求获利大于0.01。并且对路径也没有具体要求,只是最短并不超过n次,路径长度相同的情况下任何一条都是可以的。
那么!我们就抓住一个比较重要的点——转换次数。
也就是说,每转换一次,我们就将其转换成原来的货币,判断获利是否达到0.01,如果达到了,那么输出之后整个程序就结束了。(如果有多种货币超过0.01,输出其中一种即可)
所以,我们就先在外层一个for循环,循环转换次数,不可超过n。 (如果超过n就输出"no arbitrage sequence exists"好惹)。
并且!!!我们需要保存好每次转换的货币种类,最后要输出的鸭!!!
那么!大概框架出现,我们就需要写核心liao,没错,这道题的核心就是Floyd算法辣。
我们常用的Floyd一般是开一个二维数组,但其实它是三维压缩而来,所以这道题我们用三维数组ans[i][j][k],i表示第i种货币,j表示第j种货币,k表示第k次转换,整体表示从第i种货币转换成第j种货币中第k次转换时的获利。(可能有点绕8)
另外用nxt[i][j][k]表示从第i种货币转换成第j种货币中第k次转换时的货币种类。
那么!转换式就出来liao(虽然不知道为什么)!ans[i][l][k]=max(ans[i][l][k],ans[i][j][k-1]*ans[j][l][1])
它的意思就是说在前一次转化后,现在想从i转换到j,试图通过k,看能不能让值更大,能的话就变大(变大一定不吃亏,因为题目也没要求货币变成多少,只是要求要大于0.01,所以当前要是能变大的话那当然变大,可能有点贪心的意思???)
具体i j k l是啥就进程序康康8
Code:
1 #include<bits/stdc++.h>//万能头xixi(懒人福音) 2 #define MAXN 101//宏定义 3 double ans[MAXN][MAXN][MAXN]; 4 int nxt[MAXN][MAXN][MAXN];//数组意义已经解释过辣 5 int n; 6 using namespace std; 7 void print(int x,int y,int z){//最后的输出,做成函数会方便一些 8 if(z==0){//如果是第零次转换 9 printf("%d",x);//就把初始货币种类输出 10 return;//退出函数 11 } 12 print(x,nxt[x][y][z],z-1);//通过nxt数组的定义来想想这一句yo(^U^)ノ~YO 13 printf(" %d",y);//输出货币种类 14 return; 15 } 16 void solve(){//核心部分! 17 int i,tmp; 18 for(i=2;i<=n;i++){//转换次数 19 for(int j=1;j<=n;j++) 20 for(int k=1;k<=n;k++) 21 for(int l=1;l<=n;l++) 22 if(ans[k][l][i]<ans[k][j][i-1]*ans[j][l][1]){//如果从k 23 ans[k][l][i]=ans[k][j][i-1]*ans[j][l][1]; 24 nxt[k][l][i]=j;//一定要存储! 25 }//Floyd 26 int j; 27 for(j=1;j<=n;j++) 28 if(ans[j][j][i]>1.01){//如果已经达到要求 29 tmp=j; 30 break; 31 } 32 if(j<=n)//如果j符合提议,就可以跳出所有的循环惹 33 break; 34 } 35 if(i>n) 36 printf("no arbitrage sequence exists");//如果次数大于n liao 37 else 38 print(tmp,tmp,i);//输出答案 39 } 40 int main(){ 41 while(scanf("%d",&n)!=EOF){//scanf这个用法见最后 42 memset(ans,0,sizeof(ans)); 43 memset(nxt,0,sizeof(nxt));//多组数据一定要初始化!!! 44 for(int i=1;i<=n;i++) 45 for(int j=1;j<=n;j++){ 46 if(i==j){ 47 ans[i][j][1]=1;//如果是相同货币获利就是1 48 continue; 49 } 50 scanf("%lf",&ans[i][j][1]);//输入,不可以用%d哦 51 nxt[i][j][1]=j;//从i转换到j的第一次转换是j 52 } 53 solve();//进入函数 54 printf(" ");//每组数据输出后记得换行!! 55 } 56 return 0; 57 }
scanf的EOF用法:
EOF,为End Of File的缩写,通常在文本的最后存在此字符表示资料结束。
例如scanf(“%d%d”,&a,&b);
如果a b都成功输入,那么返回值为2,如果只有其中一个成功输入,那么返回值为1,如果a和b都未被成功读入,返回值为0,如果遇到错误或遇到end of file,返回值为EOF(-1)。
那么while(scanf(“%d”,&n)!=EOF)就相当于,while(cin>>n)。