题意:有N种货币,他们之间能以一定的比率交换,问能不能通过交换赚钱。最多交换N次,你的货币增加到原来的1.01倍以上才算赚钱。如果能,输出最简交换过程。
思路:DP。开一个数组DP[起始货币][当前货币][交换次数],然后循环,如果能增加换就是了。还有就是得另开一个path数组记录路径。这道题卡了我好长时间了,从期末考试前卡到现在,这道题的AC标志着我暑假刷题的开始。。
#include <iostream>
#include <stdio.h>
#include <cmath>
#include <algorithm>
#include <iomanip>
#include <cstdlib>
#include <string>
#include <memory.h>
#include <vector>
#include <queue>
#include <stack>
#include <ctype.h>
#define INF 1000000000
using namespace std;
const int maxn=22;
double map[maxn][maxn];
double DP[maxn][maxn][maxn];
int path[maxn][maxn][maxn];
int main(){
int n;
while(cin>>n){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(i==j)continue;
cin>>map[i][j];
}
}
for(int i=0;i<=n;i++){
for(int j=0;j<=n;j++){
for(int k=0;k<=n;k++){
if(i==j){
DP[i][j][k]=1.0;
}else{
DP[i][j][k]=0.0;
}
}
}
}
bool flag=false;
int start,len;
for(int k=1;k<=n;k++){//第k次交换
for(int i=1;i<=n;i++){//从i货币开始
for(int j=1;j<=n;j++){//换到j
for(int t=1;t<=n;t++){
if(j==t)continue;
if(DP[i][t][k-1]*map[t][j]>DP[i][j][k]){
DP[i][j][k]=DP[i][t][k-1]*map[t][j];
path[i][j][k]=t;
}
}
}
if(DP[i][i][k]>1.01){
start=i;len=k;
flag=true;
break;
}
}
if(flag)break;
}
if(flag){
stack<int> s;
int tmp=start;
do{
s.push(tmp);
tmp=path[start][tmp][len];
}while(len--);
while(!s.empty()){
cout<<s.top();
s.pop();
if(!s.empty())cout<<" ";
}
cout<<endl;
}else{
cout<<"no arbitrage sequence exists"<<endl;
}
}
return 0;
}