鸽了好几天终于又回来写题解了。
题意:N中不同的货币兑换来兑换去,看最后能不能赚钱,也就是用1软妹币能不能兑换到大于1的软妹币。
思路:一种货币最多兑换的次数为n,即若有A、B、C、D四种货币的话,从A出发最长的兑换路径为A->B->C->D->A,不存在比这个更长的了。
假设存在A->B->C->B->D->A这样的兑换路径,则其中存在B->C->B这条兑换路径,若其能赚钱,则问题已经得解。若其不能赚钱,则没有这样兑换的必要。
由此可知,可以用floyd算法进行求解,将加法变形为乘法,算法完毕后检查每个点到自身的边的权值是否大于1即可。
代码:
#include <iostream>
#include <fstream>
#include <string>
#include <map>
#include <algorithm>
#include <cstring>
using namespace std;
map<string,int>cur;
double dis[35][35];
void floyd(int n)
{
for (int k = 1; k <= n; k++)
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
dis[i][j] = max(dis[i][j], dis[i][k] * dis[k][j]);
}
int main()
{
//fstream cin("test.txt");
int n, m;
int k = 0;
while (cin >> n, n)
{
k++;
cur.clear();
memset(dis, 0, sizeof(dis));
string str;
for (int i = 1; i <= n; i++)
{
cin >> str;
cur[str] = i;
dis[i][i] = 1;
}
cin >> m;
string str1, str2;
double value;
for (int i = 1; i <= m; i++)
{
cin >> str1 >> value >> str2;
dis[cur[str1]][cur[str2]] = value;
}
floyd(n);
bool flag = 0;
for (int i = 1; i <= n; i++)
{
if (dis[i][i] > 1.0)
{
flag = 1;
break;
}
}
cout << "Case " << k << ": ";
if (flag)
cout << "Yes" << endl;
else
cout << "No" << endl;
}
//system("pause");
return 0;
}
其实这道题用bellman-ford的判断负权回路是更加自然的想法。主要还是我在做题之前情不自禁地看了眼题解,结果思路就被人带跑了,这种习惯真得改掉。