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

  • 相关阅读:
    Linux 虚拟机虚拟网卡问题导致无法连接问题
    使用 Load Balancer,Corosync,Pacemaker 搭建 Linux 高可用集群
    如何在 Linux 虚拟机上扩展根文件系统
    Linux 虚拟机中配置 GNOME + VNC
    在 Linux 中使用 Azure Premium 存储的基本优化指南
    如何为运行的 ARM Linux 启用 LAD2.3 版本的诊断扩展
    如何解决 Linux 虚拟机磁盘设备名不一致的问题
    Java 调用 Rest api 设置经典 Linux 虚拟机的实例启停
    CentOS: 将虚拟机迁移到 Azure (以阿里云为例)
    Linux 虚拟机的计划维护
  • 原文地址:https://www.cnblogs.com/Yz-jw/p/11480666.html
Copyright © 2011-2022 走看看