为什么我一直为这个SPOJ FISHER的解决方案获得WA?

时间:2014-11-05 14:26:13

标签: algorithm

我正在努力解决这个问题,我想我已经得到了正确答案,但我仍然得到法官的WA(错误回答)回复。

http://www.spoj.com/problems/FISHER/

提出的问题是,给定一个完整的图表,其中包含与每个边缘相关的时间和收费,在时间约束内找到从第一个节点到最后一个节点的路径并最小化收费。

与任何问题一样,有很多方法可以解决它。我的想法是扩展Floyd-Warshall算法以跟踪所有非支配路径。在算法结束时,我们以最小的成本提取路径,如果有多条路径具有相同的成本,请选择花费最少时间的路径。

抛开复杂性,不好的是,错误的答案。我不知道出了什么问题。我已经生成了一些随机图并使用了一个强力求解器(一个尝试所有可能的路径)并且它们在小(即少于11个节点)图上完全匹配。不用多说,这里是代码:

#include "stdafx.h"

// http://www.spoj.com/problems/FISHER/

// #define LOG

#include <iostream>
#include <vector>
#include <map>
#include <algorithm>

using namespace std;

int main()
{
    while (true)
    {
        int num_cities;
        int time_budget;
        vector<vector<int> > distances;
        vector<vector<int> > tolls;

        cin >> num_cities;
        cin >> time_budget;
        if (num_cities == 0 && time_budget == 0)
        {
            break;
        }
        distances.resize(num_cities);
        tolls.resize(num_cities);
        for (int i = 0; i < num_cities; i++)
        {
            distances[i].resize(num_cities);
            tolls[i].resize(num_cities);
        }
        for (int i = 0; i < num_cities; i++)
        {
            for (int j = 0; j < num_cities; j++)
            {
                int distance;
                cin >> distance;
                distances[i][j] = distance;
            }
        }
        for (int i = 0; i < num_cities; i++)
        {
            for (int j = 0; j < num_cities; j++)
            {
                int toll;
                cin >> toll;
                tolls[i][j] = toll;
            }
        }

        // Try Floyd Warshall
        // Denote the set of shortest paths from i to j going through {0,1,...k - 1} be shortest_paths[i][j][k], 
        // It is a set of shortest paths because there can be multiple shortest paths with different time used.
        // We should record if using longer time can lead to lower cost, or similarly higher cost but less time
        // The first element in the pair is the cost, the second element in the pair is time used
        vector<vector<vector<vector<pair<int, int> > > > > shortest_paths;
        shortest_paths.resize(num_cities);
        for (int i = 0; i < num_cities; i++)
        {
            shortest_paths[i].resize(num_cities);
            for (int j = 0; j < num_cities; j++)
            {
                shortest_paths[i][j].resize(num_cities + 1);
            }
        }

        // Initialization - there is only one path without going through any node
#ifdef LOG
        cout << "k = " << 0 << endl;
        cout << "<table border='1'>" << endl;
#endif
        for (int i = 0; i < num_cities; i++)
        {
#ifdef LOG
            cout << "<tr>" << endl;
#endif

            for (int j = 0; j < num_cities; j++)
            {
#ifdef LOG
                cout << "<td>(" << tolls[i][j] << ", " << distances[i][j] << ")</td>";
#endif
                shortest_paths[i][j][0].push_back(pair<int, int>(tolls[i][j], distances[i][j]));
            }
#ifdef LOG
            cout << "</tr>" << endl;
#endif
        }
#ifdef LOG
        cout << "</table>" << endl;
#endif
        // Iteration - the shortest path
        for (int k = 1; k <= num_cities; k++)
        {
#ifdef LOG
            cout << "k = " << k << endl;
            cout << "<table border='1'>" << endl;
#endif
            for (int i = 0; i < num_cities; i++)
            {
#ifdef LOG
                cout << "<tr>";
#endif
                for (int j = 0; j < num_cities; j++)
                {
                    // Step 1: Generate all candidate shortest paths
                    map<pair<int, int>, bool> candidates;
                    for (vector<pair<int, int> >::iterator pi = shortest_paths[i][j][k - 1].begin(); pi != shortest_paths[i][j][k - 1].end(); pi++)
                    {
                        candidates.insert(pair<pair<int, int>, bool>(*pi, false));
                    }
                    for (vector<pair<int, int> >::iterator fi = shortest_paths[i][k - 1][k - 1].begin(); fi != shortest_paths[i][k - 1][k - 1].end(); fi++)
                    {
                        for (vector<pair<int, int> >::iterator si = shortest_paths[k - 1][j][k - 1].begin(); si != shortest_paths[k - 1][j][k - 1].end(); si++)
                        {
                            int first_path_cost = fi->first;
                            int first_path_time_used = fi->second;
                            int second_path_cost = si->first;
                            int second_path_time_used = si->second;

                            int new_path_cost = first_path_cost + second_path_cost;
                            int new_path_time_used = first_path_time_used + second_path_time_used;

                            if (new_path_time_used <= time_budget)
                            {
                                candidates.insert(pair<pair<int, int>, bool>(pair<int, int>(new_path_cost, new_path_time_used), false));
                            }
                        }
                    }

                    vector<pair<pair<int, int>, bool> > candidates_list;
                    for (map<pair<int,int>, bool>::iterator ci = candidates.begin(); ci != candidates.end(); ci++)
                    {
                        candidates_list.push_back(*ci);
                    }

                    // Eliminate the bad ones
                    for (unsigned int p = 0; p < candidates_list.size(); p++)
                    {
                        for (unsigned int q = 0; q < candidates_list.size(); q++)
                        {
                            if (p != q)
                            {
                                int first_path_cost = candidates_list[p].first.first;
                                int first_path_time_used = candidates_list[p].first.second;
                                int second_path_cost = candidates_list[q].first.first;
                                int second_path_time_used = candidates_list[q].first.second;

                                // First take less time and less cost than second, second is eliminated
                                if (first_path_time_used <= second_path_time_used && first_path_cost <= second_path_cost)
                                {
                                    candidates_list[q].second = true;
                                }
                            }
                        }
                    }
#ifdef LOG
                    cout << "<td>";
#endif
                    for (unsigned int p = 0; p < candidates_list.size(); p++)
                    {
                        if (candidates_list[p].second == false)
                        {
#ifdef LOG
                            cout << "(" << candidates_list[p].first.first << ", " << candidates_list[p].first.second << ")<br>";
#endif
                            shortest_paths[i][j][k].push_back(candidates_list[p].first);
                        }
                    }
#ifdef LOG
                    cout << "</td>";
#endif

                }
#ifdef LOG
                cout << "</tr>" << endl;;
#endif
            }
#ifdef LOG
            cout << "</table>" << endl;
#endif
        }

        bool first = true;
        int best_cost = -1;
        int best_cost_time = -1;
        for (vector<pair<int, int> >::iterator pi = shortest_paths[0][num_cities - 1][num_cities].begin(); pi != shortest_paths[0][num_cities - 1][num_cities].end(); pi++)
        {
            if (first)
            {
                best_cost = pi->first;
                best_cost_time = pi->second;
                first = false;
            }
            else
            {
                if (pi->first < best_cost)
                {
                    best_cost = pi->first;
                    best_cost_time = pi->second;
                }
                if (pi->first == best_cost && pi->second < best_cost_time)
                {
                    best_cost_time = pi->second;
                }
            }
        }
        cout << best_cost << " " << best_cost_time << endl;
    }

    return 0;

}
/*
4 7
0 5 2 3
5 0 2 3
3 1 0 2
3 3 2 0

0 2 2 7
2 0 1 2
2 2 0 5
7 2 5 0

0 0

*/

打开LOG,您将能够看到每次迭代的Floyd Warshall表,每个单元都有一组(成本,时间)对。它们应该是所有非支配路径的成本/时间对。

如果有人能告诉我什么是错的,我真的很感激。非常感谢提前!

1 个答案:

答案 0 :(得分:1)

试试这个测试:

4 10

0 1 1 1000
1 0 1 1
1 1 0 1
1000 1 1 0

0 1 1 1
1 0 1 1
1 1 0 1
1 1 1 0

基本上你需要在

之前确保distances[i][j] <= time_budget
shortest_paths[i][j][0].push_back(pair<int, int>(tolls[i][j], distances[i][j]));