2013年「中興捧月」杯校園程序設計大賽複賽任務二解答

1、設計方案 node

複賽增長了一個條件,也正是這個條件提高了問題的難度。諸如BFS等最短路徑算法均不能求解通過指定頂點的最短路徑。雖然如此,可是能夠考慮將這個問題轉換爲求解最短路徑問題。 ios

首先計算sd的最短路徑,若是包含了全部的中間節點,顯然這就是符合條件的最優解了。若是沒有找到最短路徑,說明不存在一條路徑。比較複雜的狀況是找到了最短路徑,可是沒有包含全部中間節點。 算法

若是隻有一箇中間節點m,能夠將路徑從中間節點處分爲兩段。分別求兩段的最短路徑,若是兩段最短路徑除了m外沒有公共節點,那麼合併這兩段路徑能夠獲得最優解。兩段有除了m外的其它公共點就先計算其中一段路徑的最短路徑,從圖上去掉這個路徑所包含的節點,而後再求第二段路徑,合併能夠獲得一條從sd通過m的路徑。兩次計算能夠求得sd通過m的最短路徑。 windows

若是包含多箇中間節點就更爲複雜了。這種狀況下,考慮計算通過其中一箇中間節點的路徑。若是不存在通過某個節點的路徑那麼就不存在解。若是某條路徑包含了全部節點,那麼這條路徑是一個解。求出來全部這樣的解,其中的最短路徑是最優解。若是不存在某條路徑包含了全部的中間節點,那麼能夠知道,從sd通過每個中間點都存在一條路徑,在這種狀況下,能夠遍歷m1,m2,…,mn依次求解s->m1->…->ds->m2->…->d等,最後求得知足條件的最短路徑,但這樣得到的路徑不能保證是最短路徑。 app

若是以上方法均不能求得結果,那麼只有祭出最強神器——深度優先搜索。深度優先搜索可以遍歷全部路徑,能夠得到符合要求的最短路徑。雖然可以求得最優解,可是時間複雜度較高,在邊數較少的狀況下能夠快速求得解。爲了能在10分鐘內獲得解,在計算的過程當中檢查是否超時。 函數

2、性能 性能

本程序中,bfs的時間複雜度是O(E+V),其中E是邊數,V是節點數,解決問題須要調用O(N²)bfs(雖然最後採用dfs來保底,可是主要是以bfs來解決問題的),其中N爲中間點數目,總的運行時間是O((E+V)N²) 測試

首先,使用示例數據進行測試。 spa

zte.exe /fin.txt /oout.txt /s20 /d32 /m"22,23" 命令行

示例問題解決時間小於1秒。

下面增長几個點,而且打亂點的順序。如

zte.exe /fin.txt /oout.txt /s8 /d46 /m"37,31,47,48,39,22,23,20,45,24,32"

這個問題有11箇中間節點,解決時間小於1,能夠獲得路徑「main: 8, 45, 37, 29, 20, 21, 22, 23, 24, 32, 31, 30, 39, 4, 48, 47, 46」。

而後,本人寫了個程序用於生成一個圖,圖的節點有5000個,邊數總計有12158條。

先在5000個節點上求解幾個點。如

zte.exe /ftest.txt /oout.txt /s1 /d5000 /m"2,3,4,5,6"

解決這個問題的時間小於1秒。計算獲得的路徑爲main: 1, 35, 25, 31, 5, 2, 41, 42, 6, 3, 46, 22, 4, 50, 92, 89, 135, 179, 201, 239, 287, 336, 376, 407, 428, 458, 503, 551, 599, 644, 682, 721, 764, 806, 830, 858, 892, 940, 989, 1024, 1068, 1110, 1156, 1205, 1228, 1274, 1318, 1343, 1381, 1426, 1474, 1518, 1540, 1583, 1620, 1653, 1679, 1723, 1767, 1816, 1855, 1902, 1949, 1981, 2023, 2072, 2114, 2130, 2174, 2214, 2260, 2305, 2354, 2403, 2429, 2462, 2505, 2548, 2590, 2616, 2664, 2699, 2744, 2774, 2807, 2855, 2894, 2932, 2957, 2998, 3041, 3087, 3128, 3165, 3214, 3243, 3289, 3322, 3368, 3417, 3466, 3494, 3540, 3586, 3634, 3659, 3699, 3744, 3793, 3840, 3881, 3893, 3941, 3989, 4034, 4069, 4104, 4132, 4178, 4225, 4258, 4303, 4330, 4359, 4408, 4447, 4496, 4537, 4573, 4616, 4662, 4706, 4747, 4772, 4806, 4855, 4892, 4918, 4954, 5000

這條路徑有139個節點,下面去掉起始節點和目的節點,而後打亂路徑其它節點的順序,再求解問題,以下

zte.exe /ftest.txt /oout.txt /s1 /d5000 /m"4258,4303,4330,4359,4408,407,428,458,503,551,599,644,682,721,764,806,830,858,892,940,989,1024,1068,35,25,31,5,2,2174,2214,2260,2305,2354,2403,2429,2462,2505,2548,2590,41,42,6,3,46,22,4,50,92,2616,2664,2699,2744,2774,2807,2855,2894,2932,2957,2998,3041,3087,3128,3165,3214,3243,3289,3322,3368,3417,3466,3494,3540,3586,3634,3659,3699,3744,3793,3840,3881,3893,3941,3989,4034,4069,4104,4132,4178,4225,1110,1156,1205,1228,1274,1318,1343,1381,1426,1474,1518,1540,1583,1620,1653,1679,1723,1767,4447,4496,4537,4573,4616,4662,4706,4747,4772,4806,4855,4892,4918,4954,89,135,179,201,239,287,336,376,1816,1855,1902,1949,1981,2023,2072,2114,2130"

雖然沒有獲得最優解,可是這個問題5秒內能夠解決。獲得的路徑爲「main: 1, 35, 76, 106, 155, 179, 201, 239, 287, 336, 376, 407, 428, 458, 503, 551, 599, 644, 682, 721, 764, 806, 830, 858, 892, 940, 989, 1024, 1068, 1110, 1156, 1205, 1228, 1274, 1318, 1343, 1381, 1426, 1474, 1518, 1540, 1583, 1620, 1653, 1679, 1723, 1767, 1816, 1855, 1902, 1949, 1981, 2023, 2072, 2114, 2130, 2174, 2214, 2260, 2305, 2354, 2403, 2429, 2462, 2505, 2548, 2590, 2616, 2664, 2699, 2744, 2774, 2807, 2855, 2894, 2932, 2957, 2998, 3041, 3087, 3128, 3165, 3214, 3243, 3289, 3322, 3368, 3417, 3466, 3494, 3540, 3586, 3634, 3659, 3699, 3744, 3793, 3840, 3881, 3893, 3941, 3989, 4034, 4069, 4104, 4132, 4178, 4225, 4258, 4303, 4330, 4359, 4408, 4379, 4342, 4331, 4301, 4269, 4230, 4181, 4141, 4099, 4050, 4010, 3965, 3921, 3884, 3836, 3814, 3768, 3729, 3691, 3650, 3607, 3575, 3526, 3501, 3462, 3428, 3389, 3353, 3304, 3287, 3238, 3189, 3145, 3103, 3064, 3053, 3032, 2990, 2942, 2904, 2873, 2838, 2792, 2769, 2726, 2697, 2657, 2634, 2593, 2547, 2503, 2461, 2417, 2394, 2363, 2317, 2289, 2242, 2208, 2172, 2138, 2090, 2045, 2002, 1963, 1922, 1899, 1858, 1830, 1782, 1739, 1691, 1666, 1627, 1602, 1555, 1517, 1498, 1453, 1405, 1392, 1345, 1297, 1255, 1217, 1184, 1168, 1120, 1073, 1032, 986, 962, 927, 888, 839, 797, 755, 729, 688, 643, 628, 591, 550, 507, 485, 439, 401, 364, 316, 276, 236, 187, 149, 126, 102, 68, 25, 31, 5, 2, 41, 42, 6, 3, 46, 22, 4, 50, 92, 89, 135, 151, 197, 226, 271, 318, 360, 386, 434, 472, 493, 536, 576, 620, 658, 700, 706, 743, 785, 831, 867, 899, 944, 984, 1009, 1036, 1084, 1121, 1161, 1203, 1250, 1296, 1298, 1344, 1389, 1411, 1441, 1488, 1512, 1556, 1590, 1639, 1677, 1725, 1773, 1815, 1845, 1888, 1920, 1951, 1998, 2047, 2049, 2098, 2137, 2186, 2231, 2268, 2308, 2341, 2374, 2423, 2442, 2487, 2527, 2573, 2598, 2622, 2661, 2700, 2737, 2779, 2809, 2848, 2869, 2907, 2956, 2989, 3035, 3080, 3089, 3131, 3153, 3169, 3215, 3242, 3268, 3314, 3347, 3394, 3440, 3487, 3499, 3546, 3573, 3618, 3667, 3712, 3761, 3772, 3819, 3839, 3878, 3923, 3972, 4003, 4039, 4077, 4116, 4146, 4186, 4229, 4266, 4307, 4336, 4384, 4429, 4447, 4496, 4537, 4573, 4616, 4662, 4706, 4747, 4772, 4806, 4855, 4892, 4918, 4954, 5000」。

再把這個路徑打亂,繼續求解。

zte.exe /ftest.txt /s1 /d5000 /m"35,76,106,155,179,201,239,287,336,376,407,428,458,503,551,599,644,682,721,764,806,830,858,892,940,989,1024,1068,1110,1156,1205,1228,1274,1318,1343,1381,1426,1474,1518,1540,1583,1620,1653,1679,1723,1767,1816,1855,1902,1949,1981,2023,2072,2114,2130,2174,2214,2260,2305,2354,2403,2429,2462,2505,2548,2590,2616,2664,2699,2744,2774,2807,2855,2894,2932,2957,2998,3041,3087,3128,3165,3214,3243,3289,3322,3368,3417,3466,3494,3540,3586,3634,3659,3699,439,401,364,316,276,236,187,149,126,102,68,25,31,5,2,41,42,6,3,46,22,4,50,92,89,135,151,197,226,271,318,360,386,434,472,493,536,576,620,658,700,706,743,785,831,867,899,944,984,1009,1036,1084,1121,1161,1203,1250,1296,1298,1344,1389,1411,1441,1488,1512,1556,1590,1639,1677,1725,1773,1815,1845,1888,1920,1951,1998,2047,2049,2098,2137,2186,2231,2268,2308,2341,2374,2423,2442,2487,2527,2573,2598,2622,2661,2700,2737,2779,2809,2848,2869,2907,2956,2989,3035,3080,3089,3131,3153,3169,3215,3242,3268,3314,3347,3394,3440,3487,3499,3546,3573,3618,3667,3712,3761,3772,3819,3839,3878,3923,3972,4003,4039,4077,4116,4146,4186,4229,4266,4307,4336,4384,4429,4447,4496,4537,4573,4616,4662,4706,4747,4772,4806,4855,4892,4918,4954,3744,3793,3840,3881,3893,3941,3989,4034,4069,4104,4132,4178,4225,4258,4303,4330,4359,4408,4379,4342,4331,4301,4269,4230,4181,4141,4099,4050,4010,3965,3921,3884,3836,3814,3768,3729,3691,3650,3607,3575,3526,3501,3462,3428,3389,3353,3304,3287,3238,3189,3145,3103,3064,3053,3032,2990,2942,2904,2873,2838,2792,2769,2726,2697,2657,2634,2593,2547,2503,2461,2417,2394,2363,2317,2289,2242,2208,2172,2138,2090,2045,2002,1963,1922,1899,1858,1830,1782,1739,1691,1666,1627,1602,1555,1517,1498,1453,1405,1392,1345,1297,1255,1217,1184,1168,1120,1073,1032,986,962,927,888,839,797,755,729,688,643,628,591,550,507,485"

雖然有373箇中間點,可是隻用了兩分鐘便獲得瞭解,並且求得的解與打亂前的路徑是同一條路徑,這裏再也不列出。

3、代碼

//----------------------------------------------------------------------

// 須要包含的頭文件和使用的命名空間。

//----------------------------------------------------------------------

#include <iostream>

#include <fstream>

#include <list>

#include <queue>

#include <cstdlib>

#include <string>

#include <bitset>

#include <ctime>

#include <windows.h>

using namespace std;

 

//----------------------------------------------------------------------

// 節點數目和最大節點數目。

//----------------------------------------------------------------------

int V = 0;

time_t timer;

const int NODE_SIZE = 5001;

 

//----------------------------------------------------------------------

// 檢查是否超時。

//----------------------------------------------------------------------

bool timeout()

{

    time_t cur;

    return (time(&cur) - timer) > 600;

}

 

//----------------------------------------------------------------------

// 使用廣度優先搜索算法求解最優路徑。

//----------------------------------------------------------------------

void bfs(int graph[NODE_SIZE][NODE_SIZE], int snode, int dnode,

    int road[NODE_SIZE])

{

    //------------------------------------------------------------------

    // 若是超時再也不繼續搜索。

    //------------------------------------------------------------------

    if (timeout()) {

        return;

    }

 

    //------------------------------------------------------------------

    // 標識和前驅。

    //------------------------------------------------------------------

    static int flag[NODE_SIZE], prev[NODE_SIZE];

 

    //------------------------------------------------------------------

    // 初始化數據。

    //------------------------------------------------------------------

    for (int i = 0; i <= V; i++) {

        flag[i] = 0;

        prev[i] = 0;

    }

   

    //------------------------------------------------------------------

    // 廣度優先搜索算法。

    //------------------------------------------------------------------

    int beg = 0, end = 1;

    static int qarray[NODE_SIZE];

    flag[dnode] = 1;

    qarray[0] = dnode;

    while (beg != end) {

        int t = qarray[beg];

        for (int i = 1; i <= graph[t][0]; i++) {

            int element = graph[t][i];

            if (flag[element] == 0) {

                prev[element] = t;

                flag[element] = 1;

                qarray[end++] = element;

            }

        }

        beg++;

    }

 

    //------------------------------------------------------------------

    // 經過前驅得到路徑。

    //------------------------------------------------------------------

    if (prev[snode]) {

        int element = snode;

        road[0] = 1;

        road[1] = element;

        while (dnode != element) {

            element = prev[element];

            road[++road[0]] = element;

        }

    }

}

 

//----------------------------------------------------------------------

// 去掉某條路徑後再求解最優路徑。

//----------------------------------------------------------------------

void bfs_cond(int graph[NODE_SIZE][NODE_SIZE], int snode, int dnode,

    int cond[NODE_SIZE], int road[NODE_SIZE])

{

    //------------------------------------------------------------------

    // 去掉指定路徑。

    //------------------------------------------------------------------

    for (int i = 1; i <= cond[0]; i++) {

        int cur = cond[i];

        if (cur != snode && cur != dnode) {

            graph[cur][0] = -graph[cur][0];

        }

    }

 

    //------------------------------------------------------------------

    // 求得最優解。

    //------------------------------------------------------------------

    bfs(graph, snode, dnode, road);

 

    //------------------------------------------------------------------

    // 恢復指定路徑。

    //------------------------------------------------------------------

    for (int i = 1; i <= cond[0]; i++) {

        int cur = cond[i];

        if (cur != snode && cur != dnode) {

            graph[cur][0] = -graph[cur][0];

        }

    }

}

 

//----------------------------------------------------------------------

// 路徑是否包含全部中間節點。

//----------------------------------------------------------------------

bool has_all_mnode(int road[NODE_SIZE], int mnode[NODE_SIZE])

{

    static int flag[NODE_SIZE];

 

    for (int i = 0; i <= V; i++) {

        flag[i] = 0;

    }

 

    for (int i = 1; i <= road[0]; i++) {

        flag[road[i]] = 1;

    }

 

    for (int i = 1; i <= mnode[0]; i++) {

        if (!flag[mnode[i]]) {

            return false;

        }

    }

 

    return true;

}

 

//----------------------------------------------------------------------

// 使用深度優先搜索算法求解最優路徑。

//----------------------------------------------------------------------

void dfs(int graph[NODE_SIZE][NODE_SIZE], int snode, int dnode,

    int temp[NODE_SIZE], int htab[NODE_SIZE], int mnode[NODE_SIZE],

    int road[NODE_SIZE])

{

    //------------------------------------------------------------------

    // 若是超時再也不繼續搜索。

    //------------------------------------------------------------------

    if (timeout() || road[0] == mnode[0] + 2) {

        return;

    }

 

    //------------------------------------------------------------------

    // s等於d說明搜索到了目標。

    //------------------------------------------------------------------

    htab[snode] = 1;

    temp[++temp[0]] = snode;

    if (snode == dnode) {

        if (has_all_mnode(temp, mnode)) {

            if (road[0] == 0 || road[0] > temp[0]) {

                road[0] = temp[0];

                for (int j = 1; j <= temp[0]; j++) {

                    road[j] = temp[j];

                }

            }

        }

        htab[snode] = 0;

        temp[0]--;

        return;

    }

 

    //------------------------------------------------------------------

    // 遍歷全部路徑。

    //------------------------------------------------------------------

    for (int i = 1; i <= graph[snode][0]; i++) {

        if (htab[graph[snode][i]] != 1) {

            dfs(graph, graph[snode][i], dnode, temp, htab, mnode, road);

        }

    }

 

    //------------------------------------------------------------------

    // 遍歷全部路徑。

    //------------------------------------------------------------------

    temp[0]--;

    htab[snode] = 0;

}

 

//----------------------------------------------------------------------

// 使用深度優先搜索算法求解最優路徑。

//----------------------------------------------------------------------

void dfs(int graph[NODE_SIZE][NODE_SIZE], int snode, int dnode,

    int mnode[NODE_SIZE], int road[NODE_SIZE])

{

    static int temp[NODE_SIZE];

    static int htab[NODE_SIZE];

    road[0] = 0;

    for (int i = 0; i <= V; i++) {

        htab[i] = 0;

    }

    dfs(graph, snode, dnode, temp, htab, mnode, road);

}

 

//----------------------------------------------------------------------

// 合併兩條順序鏈接的路徑。

//----------------------------------------------------------------------

void append_path(int road[NODE_SIZE], int tail[NODE_SIZE])

{

    for (int i = 1, j = road[0]; i <= tail[0]; i++, j++) {

        road[j] = tail[i];

    }

 

    road[0] = road[0] + tail[0] - 1;

}

 

//----------------------------------------------------------------------

// 合併兩條以中間節點爲起點的路徑。

//----------------------------------------------------------------------

void form_path(int a[NODE_SIZE], int b[NODE_SIZE], int road[NODE_SIZE])

{

    road[0] = a[0] + b[0] - 1;

 

    for (int i = a[0], j = 1; i >= 1; i--, j++) {

        road[j] = a[i];

    }

 

    for (int i = 1, j = a[0]; i <= b[0]; i++, j++) {

        road[j] = b[i];

    }

}

 

//----------------------------------------------------------------------

// 查看節點是否在路徑中。

//----------------------------------------------------------------------

bool is_node_in_path(int node, int road[NODE_SIZE])

{

    for (int i = 1; i <= road[0]; i++) {

        if (road[i] == node) {

            return true;

        }

    }

    return false;

}

 

//----------------------------------------------------------------------

// 根據條件查找源節點和目的節點之間包含單箇中間節點的路徑。

//----------------------------------------------------------------------

void solve_with_node_1(int graph[NODE_SIZE][NODE_SIZE], int snode,

    int dnode, int mnode, int road[NODE_SIZE])

{

    //------------------------------------------------------------------

    // 找出以m到s、d的最短路徑,其中一條路徑不存在則知足條件的路徑也不

    // 存在,兩條路徑無共同點則拼接可得最優解,有共同點則窮舉求得路徑。

    //------------------------------------------------------------------

    static int r1[NODE_SIZE], r2[NODE_SIZE];

    road[0] = 0;

    bfs(graph, mnode, snode, r1);

    bfs(graph, mnode, dnode, r2);

 

    //------------------------------------------------------------------

    // 其中一條路徑不存在則知足條件的路徑也不存在。

    //------------------------------------------------------------------

    if (r1[0] <= 0 || r2[0] <= 0) {

        return;

    }

 

    //------------------------------------------------------------------

    // 兩條路徑無共同點則拼接可得最優解。

    //------------------------------------------------------------------

    if (r1[1] != r2[1]) {

        form_path(r1, r2, road);

        return;

    }

 

    //------------------------------------------------------------------

    // 有共同點則先去除一段路徑後再求解另外一段路徑。

    //------------------------------------------------------------------

    static int r12[NODE_SIZE], r21[NODE_SIZE];

    bfs_cond(graph, mnode, dnode, r1, r12);

    bfs_cond(graph, mnode, snode, r2, r21);

 

    //------------------------------------------------------------------

    // 比較路徑,取最優路徑。

    //------------------------------------------------------------------

    if (r12[0] > 0) {

        if (r21[0] > 0) {

            if (r1[0] + r12[0] < r2[0] + r21[0]) {

                form_path(r1, r12, road);

            } else {

                form_path(r21, r2, road);

            }

        } else {

            form_path(r1, r12, road);

        }

    } else {

        if (r21[0] > 0) {

            form_path(r21, r2, road);

        }

    }

}

 

//----------------------------------------------------------------------

// 根據條件查找源節點和目的節點之間包含多箇中間節點的路徑。

//----------------------------------------------------------------------

void solve_with_node_X(int graph[NODE_SIZE][NODE_SIZE], int snode,

    int dnode, int mnode[NODE_SIZE], int road[NODE_SIZE])

{

    //------------------------------------------------------------------

    // 若是經過某個節點的路徑包含了全部中間節點,那麼獲得解,取其中最短

    // 的路徑,若是不存在經過某個中間節點的路徑,那麼不存在解。

    //------------------------------------------------------------------

    road[0] = 0;

    for (int i = 1; i <= mnode[0]; i++) {

        static int temp[NODE_SIZE];

        solve_with_node_1(graph, snode, dnode, mnode[i], temp);

        if (temp[0] <= 0) {

            return;

        }

        if (has_all_mnode(temp, mnode)) {

            if (road[0] == 0 || road[0] > temp[0]) {

                road[0] = temp[0];

                for (int j = 1; j <= temp[0]; j++) {

                    road[j] = temp[j];

                }

                if (road[0] == mnode[0] + 2) {

                    return;

                }

            }

        }

    }

 

    //------------------------------------------------------------------

    // 上面若能獲得解確定是最優解。

    //------------------------------------------------------------------

    if (road[0] > 0) {

        return;

    }

 

    //------------------------------------------------------------------

    // 依次遍歷s->m1->...->d,s->m2->...->d,到s->mn->...->d。

    //------------------------------------------------------------------

    for (int i = 1; i <= mnode[0]; i++) {

        static int rsmy[NODE_SIZE];

        bfs(graph, snode, mnode[i], rsmy);

        if (rsmy[0] > 0) {

            //----------------------------------------------------------

            // 搜索路徑s->mX->...->mY。

            //----------------------------------------------------------

            int node = mnode[i];

            for (int j = 1; j <= mnode[0]; j++) {

                if (!is_node_in_path(mnode[j], rsmy)) {

                    int tnode;

                    static int rm2m[NODE_SIZE];

                    tnode = mnode[j];

                    rsmy[++rsmy[0]] = dnode;

                    bfs_cond(graph, node, tnode, rsmy, rm2m);

                    rsmy[0]--;

                    if (rm2m[0] <= 0) {

                        node = -1;

                        break;

                    }

                    append_path(rsmy, rm2m);

                    node = tnode;

                }

            }

 

            if (node != -1) {

                //------------------------------------------------------

                // 搜索路徑mY->d。

                //------------------------------------------------------

                static int rmyd[NODE_SIZE];

                bfs_cond(graph, node, dnode, rsmy, rmyd);

                if (rmyd[0] > 0) {

                    append_path(rsmy, rmyd);

                    //--------------------------------------------------

                    // 保存搜索到的最短路徑。

                    //--------------------------------------------------

                    if (road[0] == 0 || road[0] > rsmy[0]) {

                        road[0] = rsmy[0];

                        for (int j = 1; j <= rsmy[0]; j++) {

                            road[j] = rsmy[j];

                        }

                        if (road[0] == mnode[0] + 2) {

                            return;

                        }

                    }

                }

            }

        }

    }

 

    //------------------------------------------------------------------

    // 若是找到了路徑就返回吧,雖然這裏找到的不必定是最優的。

    //------------------------------------------------------------------

    if (road[0] > 0) {

        return;

    }

 

    //------------------------------------------------------------------

    // 若是仍是找不到,那麼只有祭出最強法寶——深度優先搜索。

    //------------------------------------------------------------------

    dfs(graph, snode, dnode, mnode, road);

}

 

//----------------------------------------------------------------------

// 根據條件查找源節點和目的節點之間的路徑。

//----------------------------------------------------------------------

int solve(const char *iname, const char *oname, int snode, int dnode,

    int mnode[NODE_SIZE])

{

    //------------------------------------------------------------------

    // 圖的鄰接矩陣。

    //------------------------------------------------------------------

    static int graph[NODE_SIZE][NODE_SIZE];

 

    //------------------------------------------------------------------

    // 清空圖。

    //------------------------------------------------------------------

    for (int i = 0; i < NODE_SIZE; i++)

        for (int j = 0; j < NODE_SIZE; j++)

            graph[i][j] = 0;

   

    //------------------------------------------------------------------

    // 從輸入文件讀取圖。

    //------------------------------------------------------------------

    ifstream ifs(iname);

    if (ifs.is_open()) {

        int a, b;

        string title;

        getline(ifs, title);

        while (!ifs.eof()) {

            char c;

            ifs >> a >> c >> b;

            graph[a][++graph[a][0]] = b;

            graph[b][++graph[b][0]] = a;

            V = V < a ? a : (V < b ? b : V);

        }

        ifs.close();

    } else {

        return -1;

    }

   

    //------------------------------------------------------------------

    // 路徑。

    //------------------------------------------------------------------

    static int road[NODE_SIZE];

 

    //------------------------------------------------------------------

    // 搜索符合條件的路徑。

    //------------------------------------------------------------------

    if (mnode[0] <= 0)

    {

        //--------------------------------------------------------------

        // 若是沒有中間節點就求s到d的最短路徑。

        //--------------------------------------------------------------

        bfs(graph, snode, dnode, road);

    }

    else

    {

        //--------------------------------------------------------------

        // 若是s到d的沒有路徑就不用繼續了。

        //--------------------------------------------------------------

        bfs(graph, snode, dnode, road);

        if (road[0] > 0)

        {

            //----------------------------------------------------------

            // 若是搜索到的路徑包含了全部中間節點,那麼這就是最優解,其

            // 它狀況下用通常的方法求解。

            //----------------------------------------------------------

            if (!has_all_mnode(road, mnode)) {

                road[0] = 0;

                solve_with_node_X(graph, snode, dnode, mnode, road);

            }

        }

    }

   

    //------------------------------------------------------------------

    // 輸出結果。

    //------------------------------------------------------------------

    ofstream ofs(oname);

    if (ofs.is_open()) {

        ofs << "main:";

        for (int i = 1; i <= road[0]; i++) {

            ofs << " " << road[i];

            if (i != road[0])

                ofs << ",";

        }

        ofs << endl;

       

    } else {

        return -1;

    }

   

    //------------------------------------------------------------------

    // 完成。

    //------------------------------------------------------------------

    return 0;

}

 

//----------------------------------------------------------------------

// 從字符串中獲取中間節點列表。

//----------------------------------------------------------------------

void get_mnode_list(const char *str, int mnode[NODE_SIZE])

{

    mnode[0] = 0;

 

    while (*str)

    {

        while (*str == ',') str++;

        mnode[++mnode[0]] = atoi(str);

        while (*str >= '0' && *str <= '9') str++;

    }

}

 

//----------------------------------------------------------------------

// 程序入口,argc是命令行參數個數,argv是命令行參數表。

//----------------------------------------------------------------------

int main(int argc, char **argv)

{

    //------------------------------------------------------------------

    // 默認的輸入文件、輸出文件、源節點、目的節點、約束條件等參數。

    //------------------------------------------------------------------

    int snode = -1;                     // 默認源節點

    int dnode = -1;                     // 默認目的節點

    int mnode[NODE_SIZE];               // 中間節點列表

    const char *iname = "in.txt";       // 默認輸入文件

    const char *oname = "out.txt";      // 默認輸出文件

 

    //------------------------------------------------------------------

    // 保存程序開始運行時的時間。

    //------------------------------------------------------------------

    timer = time(&timer);

   

    //------------------------------------------------------------------

    // 根據命令行參數肯定輸入文件、輸出文件、源節點、目的節點、約束條件

    // 等參數。

    //------------------------------------------------------------------

    while (*argv) {

        char *str = *argv++;

        if (*str++ == '/') {

            switch (*str++) {

            case 'f':

            case 'F':

                if (*str) {

                    iname = str;

                } else {

                    iname = *argv++;

                }

                break;

            case 's':

            case 'S':

                if (*str) {

                    snode = atoi(str);

                } else {

                    snode = atoi(*argv++);

                }

                break;

            case 'd':

            case 'D':

                if (*str) {

                    dnode = atoi(str);

                } else {

                    dnode = atoi(*argv++);

                }

                break;

            case 'm':

            case 'M':

                if (*str) {

                    get_mnode_list(str, mnode);

                } else {

                    get_mnode_list(*argv++, mnode);

                }

                break;

            case 'o':

            case 'O':

                if (*str) {

                    oname = str;

                } else {

                    oname = *argv++;

                }

                break;

            default:

                break;

            }

        }

    }

   

    //------------------------------------------------------------------

    // 調用solve函數解決問題。

    //------------------------------------------------------------------

    return solve(iname, oname, snode, dnode, mnode);

}

相關文章
相關標籤/搜索