菜鳥記錄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
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...