Arbitrage题解

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)。


END

原文地址:https://www.cnblogs.com/Yz-jw/p/11480666.html