Poj 上两道典型的货币兑换问题,放在一起总结下
Poj 1860 Currency Exchange
题目链接:http://poj.org/problem?id=1860
题意:有多种汇币,汇币之间可以交换,这需要手续费。例如:当你用100A币交换B币时,A到B的汇率是29.75,手续费是0.39,那么你可以得到(100 - 0.39) * 29.75 = 2963.3975 B币。问s币的金额经过交换最终得到的s币金额数能否增加。
思路:初始化时源点到其他点的距离(权值)初始化为负,求最长路,也就是获利多的一条。我们的松弛操作,就改为大于的时候更新。当源点到其他某点的距离能不断变大时,也就是存在正环,则满足题意。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const int MAXPT = 105;
const int MAXEG = 20005;
const int INF = 0x2fffffff;
double tot;
class SPFA
{
private:
int n,e;
double dis[MAXPT];
int head[MAXPT];
int cnt[MAXPT]; //cnt[i]>n则表示有正环
bool visit[MAXPT];
struct Edge
{
int v,next;
double rate,c,w;
Edge () {}
Edge (int _v, int _next, double _r,double _c)
{
v=_v;
next=_next;
rate=_r;
c=_c;
w=0;
}
}edges[MAXEG];
public:
void init (int vn)
{
n = vn;
e = 0;
for (int i=0;i<=n;i++)
{
head[i] = -1;
visit[i] = false;
dis[i] = -1; //注意赋值为负
}
}
inline void Add (int u, int v, double r,double c)
{
edges[e] = Edge(v,head[u],r,c);
head[u] = e++;
}
bool spfa (int src)
{
queue<int> que;
dis[src] = tot;
que.push(src);
visit[src] = true;
while (!que.empty())
{
int u = que.front();
que.pop();
visit[u] = false;
for (int i = head[u]; i != -1; i = edges[i].next)
{
int v = edges[i].v;
edges[i].w=(dis[u]-edges[i].c)*edges[i].rate-dis[u];
if (dis[v]<dis[u]+edges[i].w)
{
dis[v]=dis[u]+edges[i].w;
cnt[u]++;
if (visit[v]==false)
{
visit[v] = true;
que.push(v);
}
if (cnt[u]>n)
return false;
}
}
}
return true;
}
}ob;
int main ()
{
#ifdef ONLINE_JUDGE
#else
freopen("read.txt","r",stdin);
#endif
int n,m,s;
while (~scanf("%d%d%d%lf", &n,&m,&s,&tot))
{
ob.init(n);
int a, b;
double c,d;
for (int i=0;i<m;i++)
{
scanf("%d%d%lf%lf",&a,&b,&c,&d);
ob.Add(a,b,c,d);
scanf("%lf%lf",&c,&d);
ob.Add(b,a,c,d);
}
if (ob.spfa(s))
printf("NO\n");
else
printf("YES\n");
}
return 0;
}
Poj 2240 & Hdu1217 Arbitrage
题目链接:http://poj.org/problem?id=2240
有点动态规划的思想,Floyd变形
题意:给你N种货币,然后给你任意两种货币之间的汇率。如果1单位货币通过多次兑换后大于1单位,则输出Yes,否则No。
看别人解题报告发现map A<string, int> 中的string 可以用char str[...]来代替
#pragma warning (disable:4786)
#include <iostream>
#include <map>
#include <string>
#define min(x,y) ((x)<(y)?(x):(y))
using namespace std;
const int INF=10000;
double gra[35][35];
map<string,int> m;
int n,a;
void Floyd ()
{
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
for (int k=1;k<=n;k++)
if (gra[j][k]<gra[j][i]*gra[i][k])
gra[j][k]=gra[j][i]*gra[i][k];
}
int main ()
{
int i,j,Cas=1;
string str,ch;
double rate;
for (scanf("%d",&n);n;Cas++)
{
for (i=1;i<=n;i++)
for (j=i;j<=n;j++)
gra[i][j]=gra[j][i]=INF;
for (i=1;i<=n;i++)
{
cin>>str;
m[str]=i;
gra[i][i]=1.0;
}
scanf("%d",&a);
for (i=1;i<=a;i++)
{
cin>>str>>rate>>ch;
gra[m[str]][m[ch]]=rate;
}
Floyd ();
bool flag=false;
for (i=1;i<=n;i++)
if (gra[i][i]>1.0)
{
flag=true;
break;
}
if (flag)
printf("Case %d: Yes\n",Cas);
else
printf("Case %d: No\n",Cas);
scanf("%d",&n);
}
return 0;
}