zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    数组中的逆序对★★
    把数组排成最小的数★★★
    丑数★★★
    整数中1出现的次数(从1到n整数中1出现的次数)
    连续子数组的最大和
    每两个字符串中插入字符串
    linux R环境安装以及注意事项
    JAVA调用R脚本 windwos路径下
    springboot 配置多数据源
    springboot 在配置文件写参数注入到类中
  • 原文地址:https://www.cnblogs.com/Yz-jw/p/11480666.html
Copyright © 2011-2022 走看看