POJ1860(Currency Exchange)

题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=66569#problem/E

题目描述:有几种钞票,钞票间有几种互换方式(也就是常见的汇率),同样兑换时要缴纳手续费,问是否存在一种情况使兑换后所得钱比之前更多

题目思路:其实就是判断是否能够无限兑换钞票的问题(使钱不断增加的方法),可以用bellman-ford稍加改变即可。

AC代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <stack>
#include <queue>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <climits>
#define lson root<<1,l,mid
#define rson root<<1|1,mid+1,r
#define fi first
#define se second
#define ping(x,y) ((x-y)*(x-y))
using namespace std;
#define gamma 0.5772156649015328606065120 //欧拉常数
#define MOD 1000000007
#define inf 0x3f3f3f3f
#define N 10100000
#define maxn 1000100
typedef long long LL;
typedef pair<int,int> PII;

int start,n,m,head[101],index;
double d[101],money;
struct Node{
    int x,y;        ///起点终点
    double price;   ///兑换的比率
    double cost;    ///手续费
}node[300];

void add(int &x,int &y,double &p,double &v) ///加边
{
    node[index].x=x;
    node[index].y=y;
    node[index].price=p;
    node[index++].cost=v;
}

bool _solve()   ///bellman-ford算法的改用
{
    int i,j;
    memset(d,0,sizeof(d));
    d[start]=money;
    for(i=1; i<=n; ++i)
    {
        for(j=0; j<index; ++j)
        {
            int pos1=node[j].x,pos2=node[j].y;
            double temp=(d[pos1]-node[j].cost)*node[j].price; ///兑换后所得的钱
            if(temp>d[pos2])
                d[pos2]=temp;
        }
    }
    for(int j=0; j<index; ++j) ///查找是否有正权值环
    {
        int pos1=node[j].x,pos2=node[j].y;
        double temp=(d[pos1]-node[j].cost)*node[j].price;
        if(temp>d[pos2])
            return true;
    }
    return false;
}

int main()
{
    int pos,i,j,group,x,y;
    double v1,v2;
    while(scanf("%d%d%d%lf",&n,&m,&start,&money)!=EOF)   ///start最开始有哪种钞票,money最开始有多少钱
    {
        index=0;
        for(i=0; i<m; ++i)
        {
            scanf("%d%d",&x,&y);
            scanf("%lf%lf",&v1,&v2);
            add(x,y,v1,v2);
            scanf("%lf%lf",&v1,&v2);
            add(y,x,v1,v2);
        }
        if(_solve()) puts("YES");
        else puts("NO");
    }
    return 0;
}

下面是SPFA版本

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <stack>
#include <cctype>
#include <queue>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <climits>
#define lson root<<1,l,mid
#define rson root<<1|1,mid+1,r
#define fi first
#define se second
#define ping(x,y) ((x-y)*(x-y))
using namespace std;
#define gamma 0.5772156649015328606065120 //欧拉常数
#define MOD 1000000007
#define inf 0x3f3f3f3f
#define N 1001000
#define maxn 300000
typedef long long LL;
typedef pair<int,int> PII;

struct Node{
    int y; ///终点
    double p,c; ///兑换比率 以及 兑换所交手续费
    int next;  ///下个节点
}node[300];int n_cnt=0;
int l[105]; ///头节点
double d[105];  ///最大兑换金额
int vis[105];  

void init()
{
    memset(l,-1,sizeof(l));
    n_cnt=0;
}

double get(double &mo,int &cnt)  ///可得兑换金额
{
    double temp=(mo-node[cnt].c)*node[cnt].p;
    return temp;
}

int spfa(int &n,int &s,double &mo)
{
    int index[105];
    memset(index,0,sizeof(index));
    memset(d,0,sizeof(d));
    memset(vis,0,sizeof(vis));
    d[s]=mo;
    int i,j;double pri,co;
    queue<int>q;
    q.push(s);
    while(!q.empty())
    {
        i=q.front();q.pop();  /// i是起点
        if(++index[i]>n) return 1; ///入队n次则有环路
        vis[i]=0;  ///出队标志
        for(j=l[i]; j!=-1; j=node[j].next)
        {
            int pos=node[j].y;
            double temp=get(d[i],j);
            if(temp>d[pos])
            {
                d[pos]=temp;
                if(!vis[pos])
                {
                   vis[pos]=1;
                    q.push(pos);
                }
            }
        }
    }
    return 0;
}

void add(int &x,int &y,double &p,double &c) ///邻接表加边
{
    node[n_cnt].y=y;
    node[n_cnt].p=p;
    node[n_cnt].c=c;
    node[n_cnt].next=l[x];
    l[x]=n_cnt++;
}

int main()
{
    int i,j,group,x,y,m,start;
    double money,price,cost;
    //freopen("lxx.txt","r",stdin);
    while(scanf("%d%d%d%lf",&group,&m,&start,&money)!=EOF)
    {
        init();
        for(i=0; i<m; ++i){
            scanf("%d%d%lf%lf",&x,&y,&price,&cost);
            add(x,y,price,cost);
            scanf("%lf%lf",&price,&cost);
            add(y,x,price,cost);
        }
        if(spfa(group,start,money)) printf("YES\n");
        else printf("NO\n");
    }
    return 0;
}

 

加油!!!

posted @ 2016-03-23 22:12  Kurokey  阅读(289)  评论(0编辑  收藏  举报