POJ 1860 Currency Exchange

POJ 1860 Currency Exchange
大体题意:有个小朋友手里有某种货币V个,问能不能从银行通过一些骚操作把手里的这种货币变多!!.(假定她手上的货币种类是rmb吧)
思路:首先,如果能用一些骚操作把从另一种钱换回rmb,那么汇率体系一定是一个循环,可以类似A->B,B->C,C->A,也就是说,这个环是一个正环(循环之后A变多),这是最优的情况,但有可能C->A的汇率太低,导致A->B,B->C,C->A的钱变少,那么,这样就没有办法使A变多了吗?显然,我们也有办法让A变多,办法就是!让C变多.因为在题目中,不是只有三种货币,所以很有可能有很多种货币构成各种环,我们只需要让可以换成A的货币(在这里是C)变多就可以了,那么怎么使C变多呢,这又成了上面的问题,只要有一个C的正环就可以!所以这个题变成了一个递归(套娃问题),只要任何一种钱可以无限变多,A就可以变多.也就是说,只要含有一个正环,A就可以变多.这就变成了一个寻找正环的题!
下面放代码:
第一个是大佬floyd的做法(大佬说是floyd)
引用自:https://blog.csdn.net/yslcl12345/article/details/50574213

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
int n,m,s;
double map[105]={0},g1[105][105]={0},g2[101][101]={0},v;
int floyd()
{
	int i,j,k;
	double d[105];
	for(i=1;i<=n;i++)d[i]=map[i];
	for(k=1;k<=n;k++)
	   for(i=1;i<=n;i++)
	      for(j=1;j<=n;j++)
	      	if((map[i]-g2[i][j])*g1[i][j]>map[j])map[j]=(map[i]-g2[i][j])*g1[i][j];
	for(i=1;i<=n;i++)
		if(d[i]<map[i])return 1;
	return 0;
}
int main()
{
	cin>>n>>m>>s>>v;
	int i,j,k;
	for(i=1;i<=m;i++)
	{
		int a,b;
		double c,d,e,f;
		cin>>a>>b>>c>>d>>e>>f;
		g1[a][b]=c,g2[a][b]=d;
		g1[b][a]=e,g2[b][a]=f;
	}
	map[s]=v;
	floyd();
	if(floyd())cout<<"YES\n";
	else cout<<"NO\n";
	
}

下面是spfa代码:
引用自:https://www.cnblogs.com/iiyiyi/p/4703420.html

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
struct Rec
{
    int ori,des;
    double len,val;
};
const int MAXN=100+5;
int first[MAXN],next[MAXN*2];
/*用于存储邻接表*/
double dis[MAXN];
/*存储从s出发到达当前货币的最大值*/
int vis[MAXN];
/*判断某一个点是否已经存在于队列中*/ 
Rec edge[MAXN*2];
int n,m,s;
double v;

bool SPFA()
{
    memset(dis,0,sizeof(dis));
    memset(vis,0,sizeof(vis));
    queue<int> que;
    
    dis[s]=v;
    /*默认到持有货币的距离为持有货币的价值*/ 
    vis[s]=1;
    que.push(s);
    
    while (!que.empty())
    {
        int pos=que.front();
        int k=first[pos];
        vis[pos]=0; 
        que.pop();
        while (k!=-1)
        {
            if (dis[edge[k].des]<(dis[pos]-edge[k].len)*edge[k].val)
            {
                dis[edge[k].des]=(dis[pos]-edge[k].len)*edge[k].val; 
                if (!vis[edge[k].des])
                {
                    vis[edge[k].des]=1;
                    que.push(edge[k].des);
                }
            }
            k=next[k];
        }
        if (dis[s]>v) return true;
    }
    return false;
}

int main()
{
    scanf("%d%d%d%lf",&n,&m,&s,&v);
    s--;
    memset(first,-1,sizeof(first));
    
    for (int i=0;i<m;i++)
    {
        int a,b;
        double c1,r1,c2,r2;
        scanf("%d%d%lf%lf%lf%lf",&a,&b,&r1,&c1,&r2,&c2);
        a--;
        b--;
        edge[i*2].ori=edge[i*2+1].des=a;
        edge[i*2].des=edge[i*2+1].ori=b;
        edge[i*2].val=r1;
        edge[i*2].len=c1;
        edge[i*2+1].val=r2;
        edge[i*2+1].len=c2;
        
        next[i*2]=first[a];
        first[a]=i*2;
        next[i*2+1]=first[b];
        first[b]=i*2+1;
    }
    m=m*2+2;
    if (SPFA()) cout<<"YES"<<endl;
                else cout<<"NO"<<endl; 
    //system("pause");
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值