UVa Problem 104 - Arbitrage

// UVa Problem 104 - Arbitrage
// Verdict: Accepted
// Submission Date: 2011-12-22
// UVa Run Time: 0.068s
//
// 版权所有(C)2011,邱秋。metaphysis # yeah dot net
//
// [解题方法]
// 本质是求一个最小环,要求边权的积大于或等于 1.02,可以使用动态规划和 Floyd-Warshall 算法(实际上
// Floyd-Warshall 本身就已经使用了动态规划的思想)来解决本题。
//
// 用 profit(i, j, step) 表示 “由 i 经过 step 步套汇得到 j 可以得到的最大 profit 值”。则有以
// 下递推关系:
//
// profit(i, j, step) = profit(i, k, step-1) * profit(k, j, 1)
// 条件是:profit(i, k, step-1) * profit(k, j, 1) > profit(i, j, step)
// 递推初始值:profit(i, i, 1) = 1.0

#include <iostream>

using namespace std;

#define MAXN 20

double profit[MAXN + 1][MAXN + 1][MAXN + 1];
int memo[MAXN + 1][MAXN + 1][MAXN + 1];
int n;

void output(int start, int end, int step)
{
	if (step >= 2)
	{
		output(start, memo[start][end][step], step - 1);
		cout << " " << memo[start][end][step];
	}
}

int main(int argc, char *argv[])
{
	while (cin >> n)
	{
		for (int i = 1; i <= n; i++)
			for (int j = 1; j <= n; j++)
				for (int k = 1; k <= n; k++)
					profit[i][j][k] = 0.0;

		for (int i = 1; i <= n; i++)
			for (int j = 1; j <= n; j++)
				if (i == j)
				{
					profit[i][j][1] = 1;
					memo[i][j][1] = i;
				}
				else
				{
					cin >> profit[i][j][1];
					memo[i][j][1] = i;
				}

		int start, steps;
		bool arbitrage = false;

		for (int step = 2; step <= n; step++)
			for (int k = 1; k <= n; k++)
				for (int i = 1; i <= n; i++)
					for (int j = 1; j <= n; j++)
					{
						double temp = profit[i][k][step - 1] * profit[k][j][1];
						if (temp > profit[i][j][step])
						{
							profit[i][j][step] = temp;
							memo[i][j][step] = k;

							if (i == j && profit[i][j][step] > 1.01)
							{
								arbitrage = true;
								start = i;
								steps = step;
								goto out;
							}
						}
					}

out:
		if (arbitrage)
		{
			cout << start;
			output(start, start, steps);
			cout << " " << start << endl;		
		}
		else
			cout << "no arbitrage sequence exists" << endl;
	}

	return 0;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值