[PAT]A1018(Public Bike Management)踩坑及解題思路

原題回顧

PAT_A1018原文鏈接

1018 Public Bike Management (30分)

作者: CHEN, Yue
單位: 浙江大學(xué)
時(shí)間限制: 400 ms
內(nèi)存限制: 64 MB
代碼長(zhǎng)度限制: 16 KB

There is a public bike service in Hangzhou City which provides great convenience to the tourists from all over the world. One may rent a bike at any station and return it to any other stations in the city.
The Public Bike Management Center (PBMC) keeps monitoring the real-time capacity of all the stations. A station is said to be in perfect condition if it is exactly half-full. If a station is full or empty, PBMC will collect or send bikes to adjust the condition of that station to perfect. And more, all the stations on the way will be adjusted as well.
When a problem station is reported, PBMC will always choose the shortest path to reach that station. If there are more than one shortest path, the one that requires the least number of bikes sent from PBMC will be chosen.


The above figure illustrates an example. The stations are represented by vertices and the roads correspond to the edges. The number on an edge is the time taken to reach one end station from another. The number written inside a vertex S is the current number of bikes stored at S. Given that the maximum capacity of each station is 10. To solve the problem at S3, we have 2 different shortest paths:
1.PBMC -> S1 -> S3. In this case, 4 bikes must be sent from PBMC, because we can collect 1 bike from S1 and then take 5 bikes to S3, so that both stations will be in perfect conditions.
2.PBMC -> S2 -> S3. This path requires the same time as path 1, but only 3 bikes sent from PBMC and hence is the one that will be chosen.

Input Specification:

Each input file contains one test case. For each case, the first line contains 4 numbers: Cmax(≤100), always an even number, is the maximum capacity of each station; N (≤500), the total number of stations; Sp, the index of the problem station (the stations are numbered from 1 to N, and PBMC is represented by the vertex 0); and M, the number of roads. The second line contains N non-negative numbers Ci(i=1,?,N) where each Ciis the current number of bikes at Si respectively. Then M lines follow, each contains 3 numbers: Si, Sj, and Tij which describe the time Tij taken to move between stations Si and Sj. All the numbers in a line are separated by a space.

Output Specification:

For each test case, print your results in one line. First output the number of bikes that PBMC must send. Then after one space, output the path in the format: 0?>S1->...->Sp. Finally after another space, output the number of bikes that we must take back to PBMC after the condition of Sp is adjusted to perfect.
Note that if such a path is not unique, output the one that requires minimum number of bikes that we must take back to PBMC. The judge's data guarantee that such a path is unique.

Sample Input:

10 3 3 5
6 7 0
0 1 1
0 2 1
0 3 3
1 3 1
2 3 1

Sample Output:

3 0->2->3 0

解題思路及注意點(diǎn)

  • 第一遍做時(shí)立馬就選擇了用Dijkstra算法解決諸如此類最短路徑類問(wèn)題(曾自學(xué)過(guò)算法筆記,對(duì)此印象比較深刻)纷捞,但是有一個(gè)問(wèn)題是無(wú)法在路徑中確定最優(yōu)解,只能把所有最短路徑確定后,再去選擇其中最優(yōu)的一條雷绢,所以必須在其中穿插DFS算法绳军,根據(jù)前驅(qū)結(jié)點(diǎn)遞歸來(lái)得到所有路徑坤检。
  • 我對(duì)題目的第一個(gè)誤解是認(rèn)為從PBMC要么是往外帶,要么是往回帶埂陆,總之不會(huì)即帶出又帶回,這樣顯然多此一舉娃豹,按照這樣的思路寫出代碼后發(fā)現(xiàn)有兩個(gè)測(cè)試點(diǎn)未通過(guò)焚虱,于是又重新讀了幾遍題目,并經(jīng)過(guò)幾次不斷嘗試修改代碼(其實(shí)就是DFS部分)懂版,最后發(fā)現(xiàn)題目的設(shè)定是這樣的:假如路徑為 A->B->C->D鹃栽,如果在B點(diǎn)發(fā)現(xiàn)車輛不夠,需要補(bǔ)充躯畴,那么就必須要從始發(fā)地A多帶出缺少的車輛民鼓,無(wú)論此時(shí)C和D是什么狀態(tài),即使C蓬抄、D全部爆滿丰嘉,也與A沒有關(guān)系,可以理解為一直向前走不回頭嚷缭,所以饮亏,如果目的地的車輛大于滿載的一半,那么無(wú)論前面的地點(diǎn)缺多少輛車,總會(huì)把目的地多余的車輛直接送回總部克滴,與路徑上的所有點(diǎn)無(wú)關(guān)逼争。 于是將代碼的DFS部分修改后順利通過(guò)了所有測(cè)試點(diǎn)。

代碼部分

#include <cstdio>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn = 1010;
const int INF = 0x3fffffff;

int c, n, ed, m; //最大容量劝赔,頂點(diǎn)數(shù)誓焦,目的地,邊數(shù)
int G[maxn][maxn], d[maxn], weight[maxn]; //鄰接矩陣着帽,最短路徑杂伟,點(diǎn)權(quán)
vector<int> pre[maxn]; //前驅(qū)結(jié)點(diǎn)
vector<int> tempPath, Path; //當(dāng)前路徑,最優(yōu)路徑
bool vis[maxn]; //是否訪問(wèn)過(guò)
int minOut = INF, minBack = INF; //優(yōu)化結(jié)果

void Dijkstra(int s) //標(biāo)準(zhǔn)Dijkstra算法
{
    fill(d, d + maxn, INF);
    d[s] = 0;
    for (int i = 0; i <= n; i++) //因?yàn)榧由狭隧旤c(diǎn)仍翰,所以一共循環(huán)n+1次赫粥,每次都找到距離最短的點(diǎn)
    {
        int u = -1, MIN = INF; //u使d[u]最短
        for (int j = 0; j <= n; j++)
        {
            if (vis[j] == false && d[j] < MIN)
            {
                u = j;
                MIN = d[j];
            }
        }
        if (u == -1) //找不到可達(dá)點(diǎn),說(shuō)明搜索完畢
            return;
        vis[u] = true; //已訪問(wèn)
        for (int v = 0; v <= n; v++)
        {
            if (vis[v] == false && G[u][v] != INF) //未訪問(wèn)過(guò)且可到達(dá)
            {
                if (d[u] + G[u][v] < d[v])
                {
                    d[v] = d[u] + G[u][v];
                    pre[v].clear();
                    pre[v].push_back(u);
                }
                else if (d[u] + G[u][v] == d[v])
                {
                    pre[v].push_back(u);
                }
            }
        }
    }
}

void DFS(int v)
{
    if (v == 0)
    {
        tempPath.push_back(v);
        int Out = 0, Back = 0; //需要帶出的車輛數(shù)目予借,需要帶回的車輛數(shù)目
        int take = 0; //路上搜集到的自行車數(shù)目
        for (int i = tempPath.size() - 1; i >= 0; i--)
        {
            int id = tempPath[i];
            if (weight[id] > (c / 2)) //超過(guò)一半越平,加入收集量
                take += weight[id] - (c / 2);
            if (weight[id] < (c / 2))
                take -= (c / 2) - weight[id]; //不足一半,用搜集量去彌補(bǔ)灵迫,不夠的話take變?yōu)樨?fù)值
            if (take < 0) // 一旦take為負(fù)說(shuō)明從起點(diǎn)到目前的結(jié)點(diǎn)需要從基地帶出才夠
            {
                Out += abs(take); //帶出的車輛累加
                take = 0; //從基地帶出車輛彌補(bǔ)負(fù)值的take秦叛,take置0
            }
        }
        if (take > 0) //到目的地后全部補(bǔ)充完畢仍有多余車輛
            Back = take; //帶回
        else
            Back = 0; // take<=0說(shuō)明不足或剛好夠,不用帶回
        if (Out < minOut) //優(yōu)化Out
        {
            Path = tempPath;
            minOut = Out;
            minBack = Back;
        }
        else if (Out == minOut && Back < minBack)
        {
            Path = tempPath;
            minOut = Out;
            minBack = Back;
        }
        tempPath.pop_back();
        return;
    }
    tempPath.push_back(v);
    for (int i = 0; i < pre[v].size(); i++)
    {
        DFS(pre[v][i]);
    }
    tempPath.pop_back();
}

int main()
{
    fill(G[0], G[0] + maxn * maxn, INF); //初始所有結(jié)點(diǎn)之間均不可達(dá)
    scanf("%d%d%d%d", &c, &n, &ed, &m);
    for (int i = 1; i <= n; i++)
    {
        scanf("%d", &weight[i]);
    }
    weight[0] = c / 2;
    int u, v;
    for (int i = 0; i < m; i++)
    {
        scanf("%d%d", &u, &v);
        scanf("%d", &G[u][v]);
        G[v][u] = G[u][v];
    }
    Dijkstra(0);
    DFS(ed);
    printf("%d ", minOut);
    for (int i = Path.size() - 1; i >= 0; i--)
    {
        printf("%d", Path[i]);
        if (i != 0)
            printf("->");
    }
    printf(" %d\n", minBack);
    return 0;
}

跨專業(yè)數(shù)據(jù)結(jié)構(gòu)初學(xué)者瀑粥,疏漏在所難免挣跋,歡迎指正~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市狞换,隨后出現(xiàn)的幾起案子避咆,更是在濱河造成了極大的恐慌,老刑警劉巖修噪,帶你破解...
    沈念sama閱讀 211,817評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件查库,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡黄琼,警方通過(guò)查閱死者的電腦和手機(jī)膨报,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,329評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)适荣,“玉大人现柠,你說(shuō)我怎么就攤上這事〕诿” “怎么了够吩?”我有些...
    開封第一講書人閱讀 157,354評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)丈氓。 經(jīng)常有香客問(wèn)我周循,道長(zhǎng)强法,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,498評(píng)論 1 284
  • 正文 為了忘掉前任湾笛,我火速辦了婚禮饮怯,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘嚎研。我一直安慰自己蓖墅,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,600評(píng)論 6 386
  • 文/花漫 我一把揭開白布临扮。 她就那樣靜靜地躺著论矾,像睡著了一般。 火紅的嫁衣襯著肌膚如雪杆勇。 梳的紋絲不亂的頭發(fā)上贪壳,一...
    開封第一講書人閱讀 49,829評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音蚜退,去河邊找鬼闰靴。 笑死,一個(gè)胖子當(dāng)著我的面吹牛钻注,可吹牛的內(nèi)容都是我干的传黄。 我是一名探鬼主播,決...
    沈念sama閱讀 38,979評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼队寇,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了章姓?” 一聲冷哼從身側(cè)響起佳遣,我...
    開封第一講書人閱讀 37,722評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎凡伊,沒想到半個(gè)月后零渐,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,189評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡系忙,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,519評(píng)論 2 327
  • 正文 我和宋清朗相戀三年诵盼,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片银还。...
    茶點(diǎn)故事閱讀 38,654評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡风宁,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蛹疯,到底是詐尸還是另有隱情戒财,我是刑警寧澤,帶...
    沈念sama閱讀 34,329評(píng)論 4 330
  • 正文 年R本政府宣布捺弦,位于F島的核電站饮寞,受9級(jí)特大地震影響孝扛,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜幽崩,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,940評(píng)論 3 313
  • 文/蒙蒙 一苦始、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧慌申,春花似錦陌选、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,762評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至类缤,卻和暖如春臼勉,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背餐弱。 一陣腳步聲響...
    開封第一講書人閱讀 31,993評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工宴霸, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,382評(píng)論 2 360
  • 正文 我出身青樓苦掘,卻偏偏與公主長(zhǎng)得像满败,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子氓扛,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,543評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容