Bellman 算法

这道题目其实就是在求有没有正环。与求负环的区别就是要不断的更新值,但是这个值要变大。而不是变小。

Currency Exchange

Time Limit: 1000MS   Memory Limit: 30000K
Total Submissions: 20441   Accepted: 7337

Description

Several currency exchange points are working in our city. Let us suppose that each point specializes in two particular currencies and performs exchange operations only with these currencies. There can be several points specializing in the same pair of currencies.
Each point has its own exchange rates, exchange rate of A to B is the quantity of B you get for 1A. Also each exchange point has some commission, the sum you have to pay for your exchange operation. Commission is always collected in source currency.

For example, if you want to exchange 100 US Dollars into Russian Rubles at the exchange point, where the exchange rate is 29.75, and the commission is 0.39 you will get (100 - 0.39) * 29.75 = 2963.3975RUR.

You surely know that there are N different currencies you can deal with in our city. Let us assign unique integer number from 1 to N to each currency. Then each exchange point can be described with 6 numbers: integer A and B - numbers of currencies it exchanges,
and real RAB, CAB, RBA and CBA - exchange rates and commissions when exchanging A to B and B to A respectively.

Nick has some money in currency S and wonders if he can somehow, after some exchange operations, increase his capital. Of course, he wants to have his money in currency S in the end. Help him to answer this difficult question. Nick must always have non-negative
sum of money while making his operations.

Input

The first line of the input contains four numbers: N - the number of currencies, M - the number of exchange points, S - the number of currency Nick has and V - the quantity of currency units he has. The following M lines contain 6 numbers each - the description
of the corresponding exchange point - in specified above order. Numbers are separated by one or more spaces. 1<=S<=N<=100, 1<=M<=100, V is real number, 0<=V<=103.

For each point exchange rates and commissions are real, given with at most two digits after the decimal point, 10-2<=rate<=102, 0<=commission<=102.

Let us call some sequence of the exchange operations simple if no exchange point is used more than once in this sequence. You may assume that ratio of the numeric values of the sums at the end and at the beginning of any simple sequence of the exchange operations
will be less than 104.

Output

If Nick can increase his wealth, output YES, in other case output NO to the output file.

Sample Input

3 2 1 20.0
1 2 1.00 1.00 1.00 1.00
2 3 1.10 1.00 1.10 1.00

Sample Output

YES
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <limits.h>
#include <ctype.h>
#include <string.h>
#include <string>
#include <math.h>
#include <algorithm>
#include <iostream>
#include <queue>
#include <stack>
#include <deque>
#include <vector>
#include <set>
#include <map>
using namespace std;
const int INF = 99999999.9;
const int EM = 5555;
const int VM = 110;
int n,m,s;
double mon;

struct Edge{
    int u,v;
    double com;
    double exg;
}edge[EM<<1];
int cnt;
double dis[VM];
//double mon;

/*void addage(int cu,int vu,double aa,double bb){
    edge[cnt].from = cu;
    edge[cnt].to = vu;
    edge[cnt].com = aa;
    edge[cnt].exg = bb;
    cnt++;
}*/

int Bellman(){
    int i,j,flag;
    for(i=1;i<=n;i++){
        dis[i] = 0.0;
    }
    dis[s] = mon;
    for(i=1;i<n;i++){
        bool flag = false;
        for(j=0;j<cnt;j++){
            int u = edge[j].u;
            int v = edge[j].v;
            double rate = edge[j].exg;
            double cost = edge[j].com;
            if(dis[v]<(dis[u]-cost)*rate)//求最大的路径
            {
                dis[v]=(dis[u]-cost)*rate;
                flag=true;
            }
            //if(dis[edge[j].to] < (dis[edge[j].from]-edge[j].com)*edge[j].exg){
            //    dis[edge[j].to] = (dis[edge[j].from]-edge[j].com)*edge[j].exg;
            //    flag = 1;
            //}
        }
        if(flag==false){
            return false;
        }
    }
    for(j=0; j<cnt; j++)
    {
        if(dis[edge[j].v]<(dis[edge[j].u]-edge[j].com)*edge[j].exg)//与传统的bell不一样,传统的bell是找负环。现在是找正环,正环无限松弛
            return true;
    }
    return false;
}

int main(){
    //int n,m,s;
    //double mon;
    double rab,cab,rba,cba;
    int marka,markb;

    while(~scanf("%d%d%d%lf",&n,&m,&s,&mon)){
        cnt = 0;
        //flag = 1;
        while(m--){
            scanf("%d%d%lf%lf%lf%lf",&marka,&markb,&rab,&cab,&rba,&cba);
            //addage(marka,markb,a2,a1);
            //addage(markb,marka,b2,b1);
            edge[cnt].u=marka,edge[cnt].v=markb,edge[cnt].com=cab,edge[cnt].exg=rab;
            cnt++;
            edge[cnt].u=markb,edge[cnt].v=marka,edge[cnt].com=cba,edge[cnt].exg=rba;
            cnt++;
        }
        if(Bellman()){
            printf("YES\n");
        }
        else{
            printf("NO\n");
        }
    }

    return 0;
}

时间: 2024-10-12 10:47:46

Bellman 算法的相关文章

最短路径(bellman算法详解)

首先介绍一下bellman算法: Bellman-ford算法是求含负权图的单源最短路径算法,效率很低,但代码很容易写.即进行持续地松弛(原文是这么写的,为什么要叫松弛,争议很大),每次松弛把每条边都更新一下,若n-1次松弛后还能更新,则说明图中有负环,无法得出结果,否则就成功完成.Bellman-ford算法有一个小优化:每次松弛先设一个标识flag,初值为FALSE,若有边更新则赋值为TRUE,最终如果还是FALSE则直接成功退出.Bellman-ford算法浪费了许多时间做没有必要的松弛,

最短路径问题——bellman算法

关于最短路径问题,最近学了四种方法——bellman算法.邻接表法.dijkstra算法和floyd-warshall算法. 这当中最简单的为bellman算法,通过定义一个边的结构体,存储边的起点.终点和路径长度,然后通过一个while(1)死循环不断地访问每一条边,更新源点到各点的最短距离,直到没有更新时结束.这时便得到了从源点到其他点的最短距离.附上代码一段: #include<iostream>#define INF 100000000using namespace std; stru

Bellman算法PKU 3259

Wormholes Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 31593   Accepted: 11497 Description While exploring his many farms, Farmer John has discovered a number of amazing wormholes. A wormhole is very peculiar because it is a one-way p

Bellman算法

#include<stdio.h> #include<iostream> #define maxn 1000 #define inf 0x3fffffff using namespace std; struct Edage { int from; int to; int cost; }es[maxn]; int d[maxn]; int v,e; //无负圈,求单源最短路 /* 单源最短路:从一个点s到其他点的最短距离 */ void shortest_path(int s) {

Bellman算法模板

1 #include <stdio.h> 2 #include <string.h> 3 #include <algorithm> 4 using namespace std; 5 const int inf=1<<29; 6 const int N=1001; 7 int w[N][N],d[N]; 8 int u,v,c,m,n; 9 struct node 10 { 11 int from; 12 int to; 13 int c; 14 }e[N*N

轨迹压缩之Douglas-Peucker算法之Java实现

第一部分 问题描述 1.1 具体任务 本次作业任务是轨迹压缩,给定一个GPS数据记录文件,每条记录包含经度和维度两个坐标字段,所有记录的经纬度坐标构成一条轨迹,要求采用合适的压缩算法,使得压缩后轨迹的距离误差小于30m. 1.2 程序输入 本程序输入是一个GPS数据记录文件. 1.3 数据输出 输出形式是文件,包括三部分,压缩后点的ID序列及坐标.点的个数.平均距离误差.压缩率 第二部分 问题解答 根据问题描述,我们对问题进行求解,问题求解分为以下几步: 2.1 数据预处理 本次程序输入为GPS

算法训练 最短路

时间限制:1.0s   内存限制:256.0MB 问题描述 给定一个n个顶点,m条边的有向图(其中某些边权可能为负,但保证没有负环).请你计算从1号点到其他点的最短路(顶点从1到n编号). 输入格式 第一行两个整数n, m. 接下来的m行,每行有三个整数u, v, l,表示u到v有一条长度为l的边. 输出格式 共n-1行,第i行表示1号点到i+1号点的最短路. 样例输入 3 31 2 -12 3 -13 1 2 样例输出 -1-2 数据规模与约定 对于10%的数据,n = 2,m = 2. 对于

nyoj 115------城市平乱( dijkstra // bellman )

城市平乱 时间限制:1000 ms  |  内存限制:65535 KB 难度:4 描述 南将军统领着N个部队,这N个部队分别驻扎在N个不同的城市. 他在用这N个部队维护着M个城市的治安,这M个城市分别编号从1到M. 现在,小工军师告诉南将军,第K号城市发生了暴乱,南将军从各个部队都派遣了一个分队沿最近路去往暴乱城市平乱. 现在已知在任意两个城市之间的路行军所需的时间,你作为南将军麾下最厉害的程序员,请你编写一个程序来告诉南将军第一个分队到达叛乱城市所需的时间. 注意,两个城市之间可能不只一条路.

最短路算法大杂烩

最短路算法主要有以下几个: 一 Dijkstra 二 Bellman-Ford 三 SPFA 四 ASP 五 Floyd-Warshall 首先约定一下图的表示: struct Edge{         int from,to,wt;     };     vector<int>G[N];     vector<Edge>G[N]; -------------Dijkstra算法 使用条件:无负权边 复杂度O:((V+E)*log(V)) 下面是用优先队列实现的Dijkstra算