菜鳥記錄PAT甲級1003--Emergency

来源:https://www.cnblogs.com/whf10000010/archive/2023/04/13/16790110.html
-Advertisement-
Play Games

久違的PAT,由於考研408數據結構中有一定需要,同時也是對先前所遺留的競賽遺憾進行一定彌補 ,再次繼續PAT甲級1003.。 As an emergency rescue team leader of a city, you are given a special map of your coun ...


  久違的PAT,由於考研408數據結構中有一定需要,同時也是對先前所遺留的競賽遺憾進行一定彌補 ,再次繼續PAT甲級1003.。

As an emergency rescue team leader of a city, you are given a special map of your country. The map shows several scattered cities connected by some roads. Amount of rescue teams in each city and the length of each road between any pair of cities are marked on the map. When there is an emergency call to you from some other city, your job is to lead your men to the place as quickly as possible, and at the mean time, call up as many hands on the way as possible.

Input Specification:

Each input file contains one test case. For each test case, the first line contains 4 positive integers: N (500) - the number of cities (and the cities are numbered from 0 to N1), M - the number of roads, C1 and C2 - the cities that you are currently in and that you must save, respectively. The next line contains N integers, where the i-th integer is the number of rescue teams in the i-th city. Then M lines follow, each describes a road with three integers c1c2 and L, which are the pair of cities connected by a road and the length of that road, respectively. It is guaranteed that there exists at least one path from C1 to C2.

Output Specification:

For each test case, print in one line two numbers: the number of different shortest paths between C1 and C2, and the maximum amount of rescue teams you can possibly gather. All the numbers in a line must be separated by exactly one space, and there is no extra space allowed at the end of a line.

Sample Input:

5 6 0 2
1 2 1 5 3
0 1 1
0 2 2
0 3 1
1 2 1
2 4 1
3 4 1
 

Sample Output:

2 4

   就是說一個救援隊,在地圖所給N個的城市裡進行救援,每個城市之間有M條路進行連接且有一定數量的救援人員,C1是初始地點,C2是目的地。

  所需輸入第一行是:城市數量、路徑數量、初始地、目的地

      第二行是:各城市所包含的救援人數(共N個數據)

      接下來的M行:地點1、地點2、1,2間的距離L

  所得輸出:最短路徑的數量、最多得到的救援人數

題目分析

    一眼圖的遍歷,那麼能用到的方法很多,例如廣度優先、深度優先、迪傑斯特拉等等,筆者在此用深度優先,迪傑斯特拉等“高級”演算法往後更新。

    要清楚整體大概思路:首先對數值進行輸入,對於數組,初始化應是儘可能大還是儘可能小?然後深度遍歷各節點時,如何遍歷下去的條件是什麼?如何選擇路徑,到達目的地之前應該怎麼進入下一個節點?達到目的地後,如何判斷是最小路徑?如何記錄和比較最多救援人數?

個人想法

    那麼首先對於變數的設置

1 int N, M, C1, C2;//題目所給城市數量、路徑數量、初始地、目的地
2 int c1, c2, l, dis[501][501];//二維數組dis用於記錄我們所輸入的M行中地點1和地點2之間的距離l3 int paths, teams;//輸出的兩個結果:路徑數,人員數
4 int mindis[501];//計算過程中記錄某條路勁上的當前最短路徑
5 int* cteam;//各城市的救援人數,這裡其實是個數組,寫成指針是為了方便在主函數中進行記憶體管理malloc和初始化memset

    我在此均設為全局變數,因為在後續的編寫中我發現會單獨寫出一個dfs函數,而用全局變數可以更容易調用。要清楚設為數組的條件是記錄多條數據,再次如城市是否連接,各城市間的路徑長度,各城市的救援人數,遍歷每條路徑所需要的各路徑總長度(涉及比較和有下標組成的路徑標識,所以需要數組記錄,單純的變數無法做到),其次對於函數的中間變數我採取即寫即設,並沒有在開始就儘可能將其完全想到。

    然後編寫數據的輸入和輸出。

1 //初始化dis數組,不相連的無窮大距離,自身0距離or-1?,表示距離的同時表示有無連接 
2 for (int i = 0; i < 501; i++) 
3 for (int j = 0; j < 501; j++)
 4     if (i == j)dis[i][j] = 0;//自身距離
 5        else
 6         dis[i][j] = 9999999;//設為無窮大
 7    
 8     scanf("%d%d%d%d", &N, &M, &C1, &C2);

 9     cteam = malloc(sizeof(int) * 4);
10     memset(cteam, 0, sizeof(cteam) * 4);//記錄每個城市的team數,初始為0個救援人員
11     for (int i = 0; i < N; i++) {
12         scanf("%d", &cteam[i]);  
13     }
14     for (int i = 0; i < M; i++) {
15         scanf("%d%d%d", &c1, &c2, &l);
16         dis[c1][c2] = l;    
17         dis[c2][c1] = l;    //無向圖,c1->c2==c2->c1,所以兩個距離相等
18     }
19     for (int i = 0; i < 501; i++)mindis[i] = 9999999;  //需要註意的是這裡mindis用於存放某條路徑的長度,設為一個無窮大的是為了在後續比較中讓我們所輸入的“非無窮大”的距離記錄並比較
                                   //換句話說,如果這裡初始為0,那麼往後輸入、記錄的每條有效路徑的長度都會大於0,從而導致最短路徑無法更新

20     dfs(C1, 0, cteam[C1]);//深度遍歷函數
21     printf("%d %d", paths, teams);

 

    接下來就是dfs函數的編寫,在次先回答分析階段的幾個問題。

  深度遍歷各節點時,如何遍歷下去的條件是什麼?

  條件就是我們的答案,即最短路徑(這裡沒加上最多人數是因為得到最多人數的前提是所得的最短路徑存在),所以應該滿足當前所走的路徑curlen小於目前為止該地的最短路徑mindis[curcity],到這其實也發現mindis數組不僅記錄到該節點有無被訪問,也記錄歷來被訪問時所經歷的最短路徑!所以如果大於mindis,那麼說明這條路徑肯定不是最短,可以直接返回到上一個路徑並重新選擇路線;反之就繼續遍歷。

  如何選擇路徑,到達目的地之前應該怎麼進入下一個節點?

   筆者個人對於這種所需函數相同,且需要記錄的題目總是會想到迭代,大部分時候都是管用的。所以在此就是不斷迭代,每次迭代下一個位置的節點、目前所走長度curlen+當前與下一個節點的距離dis、目前所有人員數+下一個節點所有人員數。

  達到目的地後,如何判斷是最小路徑?如何記錄和比較最多救援人數?

   該路徑目前的長度curlen是否與目標地的mindis相同,(第一次遍歷的時候應是不同)不同時,將path歸為1,記錄當前team人數,並將此時的curlen視為最短路徑對目標地的mindis賦值;相同時,path++,比較並記錄最新的最多人數。這裡指出  必須分為不同或相同的情況,不可以大於或小於 --> path在此時總是歸為1,因為如果大於mindis只會存在第一次到達目的地時mindis初始無窮大的狀態,後續在抵達,如果有比第一次到達路徑長的情況會在往次迭代被終止;如果小於,那麼最短路徑和數量就會更新,path歸為1。

 1 void dfs(int curcity, int curlen, int curteam) {//每次傳入節點,路徑長,隊伍人員
 2     if (curlen > mindis[curcity])return;      //如果比該節點所記錄的最短路徑要短,直接退出
 3     if (curcity == C2) {                //到達目的地,並判斷是否是最短路徑
 4         if (curlen != mindis[curcity]) {      //是最新的最短路徑
 5             paths = 1;
 6             mindis[C2] = curlen;
 7             teams = curteam;
 8         }
 9         else {                      //相同的最短路徑
10             paths++;
11             if (curteam > teams)teams = curteam;
12         }
13     }
14     else
15     {
16         if (curlen < mindis[curcity])mindis[curcity] = curlen;    //不大於當前最短路徑時,更新最短節點  
17         for (int i = 0; i < 501; i++) {
18             if (dis[curcity][i] != 9999999 && i != curcity)      //遍歷每個節點,同時選擇有效路徑進行迭代
19                 dfs(i, curlen + dis[curcity][i], curteam + cteam[i]);//疊加路徑長度和人員數量
20         }
21     }
22 }

 

 

<-----------------------------------完整代碼----------------------------------->

 

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int N, M, C1, C2;
int c1, c2, dis[501][501];
int l;
int paths, teams;
int mindis[501];
int* cteam;
void dfs(int curcity, int curlen, int curteam) {
    if (curlen > mindis[curcity])return;
    if (curcity == C2) {
        if (curlen != mindis[curcity]) {
            paths = 1;
            mindis[C2] = curlen;
            teams = curteam;
        }
        else {
            paths++;
            if (curteam > teams)teams = curteam;
        }
    }
    else
    {
        if (curlen < mindis[curcity])mindis[curcity] = curlen;
        for (int i = 0; i < 501; i++) {
            if (dis[curcity][i] != 9999999 && i != curcity)
                dfs(i, curlen + dis[curcity][i], curteam + cteam[i]);
        }
    }
}

int main() {
    //初始化dis數組,不相連的無窮大距離,自身0距離or-1?
    for (int i = 0; i < 501; i++)
        for (int j = 0; j < 501; j++)
            if (i == j)dis[i][j] = 0;
            else
                dis[i][j] = 9999999;//設為無窮大
   
    scanf("%d%d%d%d", &N, &M, &C1, &C2);
    cteam = malloc(sizeof(int) * 4);
    memset(cteam, 0, sizeof(cteam) * 4);//記錄每個城市的team數
    for (int i = 0; i < N; i++) {
        scanf("%d", &cteam[i]);
    }
    for (int i = 0; i < M; i++) {
        scanf("%d%d%d", &c1, &c2, &l);
        dis[c1][c2] = l;
        dis[c2][c1] = l;
    }
    for (int i = 0; i < 501; i++)mindis[i] = 9999999;
    dfs(C1, 0, cteam[C1]);
    printf("%d %d", paths, teams);
    return 0;
}
View Code

最後最後

 

 我自己的VS2022多次實驗是沒有問題的,但是PAT就。。。。

 

多次調試甚至結果都沒有,只是提醒scanf出現return問題,反覆看了很多次無解,就很無奈。。。在此還是希望各位看官可以幫我找找問題並指正,不勝感激!

 

 

 

總結

    第三題從某種意義來說是真正需要思考的題目,考的雖然是圖,但還是很簡單的一種,對於此題,無它,看懂圖,理清每條思路即可,有必要說的是,對於競賽也好,Leecode和洛也好,c的問題貌似總是大於c++的,也不知道現在改c++還能不能來的及。。。

    感謝您能看到這,菜鳥記錄,挑戰每種錯誤的極限!

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 當瀏覽器載入網頁時,通常會遵循一個預設的流程,先載入 HTML、CSS 和 JavaScript,然後再載入圖片、音頻、視頻等資源。這個預設的流程可能會導致網頁載入速度變慢,用戶體驗不佳。因此,可以使用一些技術來優化網頁載入的速度,其中之一就是按需載入。 按需載入是指根據用戶實際需要,動態地載入資源 ...
  • 1.準備工作:HbuiderX + 微信開發者工具下載安裝+小程式賬號申請開通(這裡就不例舉了,可以看同賬號uniapp小程式開發準備) 2.創建項目 新版本的HbuilderX點擊新建項目——選擇uni-app——選擇預設模板——輸入項目名稱——選擇Vue版本(此隨筆是前後端分離開發,不使用Uni ...
  • css基礎:塊元素、內聯元素、內聯塊元素 CSS中,html中的標簽元素大體被分為三種不同的類型:塊狀元素、內聯元素(又叫行內元素)和內聯塊狀元素。 1.常用的塊狀元素有: <div>、<p>、<h1>-<h6>、<ol>、<ul>、<dl>、<table>、<address>、<blockquot ...
  • 本文從攻擊者角度和防禦者角度詳細解析前端代碼安全與混淆的相關知識,總結了大部分攻擊者共同點以及如何應對普通開發者外掛程式和Pyhton 爬蟲 ...
  • 讓對象保持消息靈通 #01需求 一個WeatherData對象負責追蹤目前的天氣狀況(溫度,濕度,氣壓)。希望你們能建立一個應用,有三種佈告板,分別顯示目前的狀況、氣象統計及簡單的預報。當WeatherObject對象獲得最新的測量數據時,三種佈告板必須實時更新。而且,這是一個可以擴展的氣象站,We ...
  • 簡介 解釋器模式(Interpreter Pattern)是一種行為型設計模式。這種模式實現了一個表達式介面,該介面解釋一個特定的上下文。這種模式常被用在 SQL 解析、符號處理引擎等。 解釋器模式常用於對簡單語言的編譯或分析實例中,為了掌握好它的結構與實現,必須先瞭解編譯原理中的“文法、句子、語法 ...
  • 本文探討了 API 管理在數字化轉型中的重要性,以及 API 管理面臨的挑戰和發展機遇。文章重點介紹了十大 API 管理髮展趨勢,包括 API 安全性、API 標準化、雲端 API 管理解決方案、低代碼 API 平臺、API 市場、新興 API 協議、人工智慧與 API、開發者體驗、API 分析和無 ...
  • 軟體開發: 唯一不變的是變化: 不管設計的多好,隨著時間推移,應用必定成長和變更 設計原則: 封裝變化:設別應用中變化的方面,把它們和不變的方面分開; (把會變化的部分取出並封裝,這樣,就可以修改或者擴展這個部分,而不會影響其他不需要變化的部分) 針對介面編程,而不是針對實現編程(介面,實際上就是針 ...
一周排行
    -Advertisement-
    Play Games
  • 前言 本文介紹一款使用 C# 與 WPF 開發的音頻播放器,其界面簡潔大方,操作體驗流暢。該播放器支持多種音頻格式(如 MP4、WMA、OGG、FLAC 等),並具備標記、實時歌詞顯示等功能。 另外,還支持換膚及多語言(中英文)切換。核心音頻處理採用 FFmpeg 組件,獲得了廣泛認可,目前 Git ...
  • OAuth2.0授權驗證-gitee授權碼模式 本文主要介紹如何筆者自己是如何使用gitee提供的OAuth2.0協議完成授權驗證並登錄到自己的系統,完整模式如圖 1、創建應用 打開gitee個人中心->第三方應用->創建應用 創建應用後在我的應用界面,查看已創建應用的Client ID和Clien ...
  • 解決了這個問題:《winForm下,fastReport.net 從.net framework 升級到.net5遇到的錯誤“Operation is not supported on this platform.”》 本文內容轉載自:https://www.fcnsoft.com/Home/Sho ...
  • 國內文章 WPF 從裸 Win 32 的 WM_Pointer 消息獲取觸摸點繪製筆跡 https://www.cnblogs.com/lindexi/p/18390983 本文將告訴大家如何在 WPF 裡面,接收裸 Win 32 的 WM_Pointer 消息,從消息裡面獲取觸摸點信息,使用觸摸點 ...
  • 前言 給大家推薦一個專為新零售快消行業打造了一套高效的進銷存管理系統。 系統不僅具備強大的庫存管理功能,還集成了高性能的輕量級 POS 解決方案,確保頁面載入速度極快,提供良好的用戶體驗。 項目介紹 Dorisoy.POS 是一款基於 .NET 7 和 Angular 4 開發的新零售快消進銷存管理 ...
  • ABP CLI常用的代碼分享 一、確保環境配置正確 安裝.NET CLI: ABP CLI是基於.NET Core或.NET 5/6/7等更高版本構建的,因此首先需要在你的開發環境中安裝.NET CLI。這可以通過訪問Microsoft官網下載並安裝相應版本的.NET SDK來實現。 安裝ABP ...
  • 問題 問題是這樣的:第三方的webapi,需要先調用登陸介面獲取Cookie,訪問其它介面時攜帶Cookie信息。 但使用HttpClient類調用登陸介面,返回的Headers中沒有找到Cookie信息。 分析 首先,使用Postman測試該登陸介面,正常返回Cookie信息,說明是HttpCli ...
  • 國內文章 關於.NET在中國為什麼工資低的分析 https://www.cnblogs.com/thinkingmore/p/18406244 .NET在中國開發者的薪資偏低,主要因市場需求、技術棧選擇和企業文化等因素所致。歷史上,.NET曾因微軟的閉源策略發展受限,儘管後來推出了跨平臺的.NET ...
  • 在WPF開發應用中,動畫不僅可以引起用戶的註意與興趣,而且還使軟體更加便於使用。前面幾篇文章講解了畫筆(Brush),形狀(Shape),幾何圖形(Geometry),變換(Transform)等相關內容,今天繼續講解動畫相關內容和知識點,僅供學習分享使用,如有不足之處,還請指正。 ...
  • 什麼是委托? 委托可以說是把一個方法代入另一個方法執行,相當於指向函數的指針;事件就相當於保存委托的數組; 1.實例化委托的方式: 方式1:通過new創建實例: public delegate void ShowDelegate(); 或者 public delegate string ShowDe ...