题意:有若干种货币,并给出其互相交换的汇率,问能不能找到一个小于n的环使起始点的货币交换之后增长超过1%。
思路:这道题坑了两个小时,一开始看他数据量比较小才20就想用搜索剪枝,后来仔细算了一下还是会超时的,再后来就去看解题报告了。果断想的方向就错了,其实是动态规划状态一看就知道该怎么写了=。=和floyd很像的。dis[i][j][k]表示从i到j交换k次所获得的最大收益。然后四重循环每次枚举中间结点v并从dis[i][v][k-1]转移过来。别忘了转的时候要记录路径。算好之后从1-k扫描一有超过1.01就打印路径即可。
代码如下:(我写的比较长0.0)
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <algorithm> 6 #include <utility> 7 #include <stack> 8 #include <queue> 9 #include <vector> 10 #define INF 500001 11 #define LEN 110 12 13 using namespace std; 14 15 int n, path[LEN][LEN][LEN]; 16 double Map[LEN][LEN], dis[LEN][LEN][LEN]; 17 18 void floyd() 19 { 20 memset(dis, 0, sizeof dis); 21 memset(path, 0, sizeof path); 22 for(int i=1; i<=n; i++){ 23 for(int j=1; j<=n; j++){ 24 dis[i][j][1] = Map[i][j]; 25 path[i][j][1] = i; 26 } 27 } 28 for(int k=2; k<=n; k++){ 29 for(int v=1; v<=n; v++){ 30 for(int i=1; i<=n; i++){ 31 for(int j=1; j<=n; j++){ 32 if(dis[i][j][k]<dis[i][v][k-1]*dis[v][j][1]){ 33 dis[i][j][k] = dis[i][v][k-1]*dis[v][j][1]; 34 path[i][j][k] = v; 35 } 36 } 37 } 38 } 39 } 40 } 41 42 void print(int x, int y, int k){ 43 if(k==1)printf("%d", path[x][y][k]); 44 else{ 45 print(x, path[x][y][k-1], k-1); 46 printf(" %d", y); 47 } 48 } 49 50 int main() 51 { 52 // freopen("in.txt", "r", stdin); 53 54 while(scanf("%d", &n)!=EOF){ 55 for(int i=1; i<=n; i++){ 56 for(int j=1; j<=n; j++){ 57 if(i==j){Map[i][j] = 0;continue;} 58 scanf("%lf", &Map[i][j]); 59 } 60 } 61 floyd(); 62 int f = 0, pos; 63 for(int k=1; k<=n; k++){ 64 for(int i=1; i<=n; i++){ 65 if(dis[i][i][k] >= 1.01){ 66 f = 1;pos = i;break; 67 } 68 } 69 if(f){ 70 print(pos, pos, k+1); 71 printf(" "); 72 break; 73 } 74 } 75 if(f==0)printf("no arbitrage sequence exists "); 76 } 77 return 0; 78 }