poj1860解题报告(两种解法)

来源:互联网 发布:喜报制作软件下载 编辑:程序博客网 时间:2024/06/16 08:18

给定一些站点可以交换货币,判断持有某一种货币的人是否可以增值财产.

解法1:基本思路是寻找一个正环,包含出发点s.没有用Bellman_ford算法,采用的是深度搜索优先(DFS),当一个节点被访问过之后,再次访问,就说明找到了一条回路.这时候需要判断找到的回路是不是正的.比较当前节点的货币数量与出发时节点的货币数量(一个节点可能有很多货币状态,因为可以通过不同的途径到达该节点,所以需要利用一个栈把状态保存起来),当前状态和前一个入栈的状态就是应该比较的对象.如果满足就退出函数.

//解法1为了验证答案,从txt文档里面读入了大量数据作测试,没有按照poj上的手动输入.

#include "iostream"#include "fstream"#include "sstream"#include "string"#include "vector"using namespace std;struct record{    int next;    double rate;    double com;};struct List{    int index;    vector<record> ptr;};typedef  vector<List> G;int N, M, S;double V;bool isvisited[101] = { false };int a, b;double r1, c1, r2, c2;static bool isyes = false;inline double convert(double money, double rate, double commision){    return ((money - commision)*rate) ;//返还转换的钱}void func(int sort, double money, const vector<List> &graph,    vector<vector<double>>& Money,vector<int>& indegree){    //sort代表当前所在的节点    const vector<record> &temp = graph[sort].ptr;    if (indegree[sort] < 0||money<=0)        return;    else if (isvisited[sort])//说明该节点被访问过,找到一个环    {        vector<double>::iterator p = (Money[sort].end() - 2);        if (money>*p)//一个正环        {            isyes = true;            cout << sort << endl;        }        return;    }    isvisited[sort] = true;    for (int it = 0; it != temp.size()&&isyes!=true; ++it)//    {        int index = (temp[it]).next;        double rate = (temp[it]).rate, com = (temp[it]).com;        -- indegree[index];        Money[index].push_back(convert(money, rate, com));        func(index, Money[index].back(),graph,Money,indegree);        Money[index].pop_back();        ++indegree[index];    }    isvisited[sort] = false;}int main(){    string line;    ifstream is("Text.txt");    getline(is, line);    istringstream R1(line);    R1 >> N >> M >> S >> V;    G graph(N + 1);    vector<int> indegree(N + 1);    vector<vector<double>> Money(N + 1);    int x = M;    while (x--)    {        if (is)        {            is.clear();            getline(is,line);            istringstream R(line);            while (R >> a >> b >> r1 >> c1 >> r2 >> c2)            {                record temp1 = { b, r1, c1 };            graph[a].ptr.push_back(temp1);//存入一个相邻节点            record temp2 = { a, r2, c2 };            graph[b].ptr.push_back(temp2);            ++indegree[a], ++indegree[b];//入度加一            }                   }    }    //寻找一个环,起点为S    Money[S].push_back (V);    func(S,V,graph,Money,indegree);    if (isyes)        cout << "YES" << endl;    else        cout << "NO" << endl;    return 0;}

解法二:采用网上普遍的Bellman_ford算法,寻找一个环,并且按照货币兑换的方式来进行松弛.基本就是算法导论上的思路。

#include "iostream"#include "fstream"#include "sstream"#include "string"#include "vector"using namespace std;int N, M, S,a,b;double r1,c1,r2,c2,V;const double Inf = 1000000000;struct Edge{    int beg;    int end;    double r, c;};typedef vector<Edge> E;typedef vector<double> Dis;bool relax(Edge& one_edge,Dis &D){    double result = (D[one_edge.beg] - one_edge.c)*one_edge.r;    if (result > D[one_edge.end])    {        D[one_edge.end] = result;        return true;    }    else        return false;}bool bellman_ford(E edge,Dis &D){    //初始化已经在外部完成    for (size_t i = 1; i != N; ++i)//遍历|V|-1个点    {        bool flag = false;        for (auto &it : edge)        {            if (relax(it,D)) flag = true;//本次松弛成功了至少一次        }        if (D[S] > V) return true;        if (!flag)  return false;//本次遍历没有进行松弛,且没有找到正环    }    //检测是否找到正环    for (auto &it : edge)        if (relax(it,D)) return true;//如果还能松弛,说明存在正环    return false;}int main(){    cin >> N >> M >> S >> V;    E edge(M + 1);    vector<double> D (N+1);    D[S] = V;    while (M--)    {        cin >> a >> b >> r1 >> c1 >> r2 >> c2;        Edge temp = { a, b, r1, c1 }, temp2 = { b, a, r2, c2 };        edge.push_back(temp), edge.push_back(temp2);    }    bool ans = bellman_ford(edge, D);    if (ans)        cout << "YES" << endl;    else        cout << "NO" << endl;    return 0;}
0 0
原创粉丝点击