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> 2 #define MAXN 5001 3 using namespace std; 4 __int128 n,r,g,t,b,Ans;//懒于打高精hhhh 5 __int128 ans[MAXN][MAXN];//二维ans[i][j]来表示前i个塔有j个干扰塔,则有i-j个放射塔,n-i个激光塔 6 int read(); 7 void print(__int128 x){ 8 if(x>9) print(x/10); 9 putchar(x%10+'0');//int128是直接输出不了der,所以要这个亚子输出 10 } 11 int main(){ 12 //freopen("antbuster.in","r",stdin); 13 //freopen("antbuster.out","w",stdout); 14 n=read(),r=read(),g=read(),b=read(),t=read();//快读 15 for(int i=1;i<=n;i++) 16 ans[i][0]=(i-1)*g*t+ans[i-1][0];//初始化,若n个点上全部都放上放射塔 17 for(int i=1;i<=n;i++) 18 for(int j=1;j<i;j++) 19 ans[i][j]=max(ans[i-1][j-1]+(i-j)*g*(t+(j-1)*b),ans[i-1][j]+(i-j-1)*g*(t+j*b)); 20 //共i个点,放j个干扰塔的情况 21 for(int i=0;i<=n;i++) 22 for(int j=0;j<=i;j++) 23 Ans=max(ans[i][j]+r*(n-i)*(t+j*b)+(i-j)*g*(n-i)*(t+j*b),Ans); 24 //n个点上,i个塔已经放置,剩下n-i个塔全部放置激光塔 25 print(Ans);//输出 26 return 0; 27 } 28 int read()//快读 29 { 30 int x=0,k=1;char ch=' '; 31 while(!isdigit(ch)){ 32 ch=getchar(); 33 if(ch=='-') k=-1; 34 } 35 while(isdigit(ch)){ 36 x=x*10+ch-'0'; 37 ch=getchar(); 38 } 39 return k*x; 40 }