1. 程式人生 > 實用技巧 >PAT甲級1149Dangerous Goods Packaging

PAT甲級1149Dangerous Goods Packaging

題目連結

https://pintia.cn/problem-sets/994805342720868352/problems/1038429908921778176

題目要求

當用容器運輸貨物時,一些貨物是不能裝在一起的。現在告訴你哪些貨物能裝在一起,給你一些貨物,請判斷這些貨物是否可以被裝在一起

  • 輸入

    • N:不能裝在一起的貨物對的數量,不超過10000

    • M:要運輸的貨物的組數,不超過100

    • N組不能裝在一起的貨物:每組包括兩個貨物索引

    • M組貨物

      第一個數字K(不超過1000)是貨物的數量,然後剩下的是貨物索引(5位數字)

  • 輸出

    對於M組貨物中的每組,如果其中沒有不可以裝在一起的貨物則輸出Yes,否則輸出No

題解一

思路

這個思路會超時

  1. 通過map和hash記錄兩個貨物是否可以被裝在一起,相當於一個鄰接矩陣
    • 為什麼不定義矩陣?如果要用矩陣,在這裡就需要定義一個100000×100000的bool矩陣,大概會佔用10GB,而記憶體限制是64MB。
  2. 對於每組貨物,兩兩判斷是否不相容,是一個兩層迴圈,時間複雜度是\(K^2\),再算上M組查詢,時間複雜度就是\(MK^2\),最大值為100×1000×1000=1e8,大概會耗時1秒,肯定會超過400ms的時間限制。

程式碼

// Problem: PAT Advanced 1149
// URL: https://pintia.cn/problem-sets/994805342720868352/problems/1038429908921778176
// Tags: Graph Map Hash

#include <iostream>
#include <unordered_map>
#include <vector>
using namespace std;

int main()
{
    int n, m, k;
    scanf("%d %d", &n, &m);

    int good1, good2;
    unordered_map<int, bool> incompatible; // 通過map和hash記錄兩個貨物是否可以被裝在一起
    
    while (n--){ // 通過map和hash記錄兩個貨物是否可以被裝在一起
        scanf("%d %d", &good1, &good2);
        incompatible[good1 * 100000 + good2] = true;
        incompatible[good2 * 100000 + good1] = true;
    }

    while (m--){ //判斷m組貨物
        scanf("%d", &k);
        vector<int> goods(k);
        for (int i = 0; i < k; i++) // 記錄k個貨物
            scanf("%d", &goods[i]);
        
        bool isYes = true;
        for(int i = 0; i < k - 1; i++){ //判斷k個貨物是否可以放在一起
            good1 = goods[i];
            for (int j = i + 1; j < k; j++){
                good2 = goods[j];
                if (incompatible[good1 * 100000 + good2] || incompatible[good2 * 100000 + good1]){
                    isYes = false;
                    break;
                }
            }
        }

        // 輸出結果
        if (isYes)
            printf("Yes\n");
        else
            printf("No\n");        
    }

    return 0;
}

題解二

思路

  1. 使用鄰接表儲存每個貨物的不能裝在一起的貨物

  2. 對於每組貨物,使用一維陣列儲存每個貨物是否在這組貨物中

  3. 查詢鄰接表,並通過一維陣列判斷每個貨物的不相容貨物是否出現在這組貨物中

    這裡也是用了兩層迴圈,但這兩層迴圈的時間複雜度是\(N\),再算上M組查詢,時間複雜度就是\(MN\),最大值為100×10000=1e6。

程式碼

// Problem: PAT Advanced 1149
// URL: https://pintia.cn/problem-sets/994805342720868352/problems/1038429908921778176
// Tags: Graph Map Hash

#include <iostream>
#include <vector>
using namespace std;

vector<int> incompatible[100000]; // 鄰接表,貨物與哪些貨物不能裝在一起

int main()
{
    int n, m, k, good1, good2;
    scanf("%d %d", &n, &m);
    while (n--){  // 建立鄰接表
        scanf("%d %d", &good1, &good2);
        incompatible[good1].push_back(good2);
        incompatible[good2].push_back(good1);
    }

    while (m--){ // m組貨物
        scanf("%d", &k);
        vector<int> goods(k); // 該組貨物
        bool contained[100000]={false}; // 該組貨物中有哪些貨物
        for (int i = 0; i < k; i++){ // 記錄該組貨物
            scanf("%d", &goods[i]);
            contained[goods[i]] = true;
        }

        bool isYes = true;
        for (int i = 0; i < k; i++){ // 查詢鄰接表,並通過一維陣列判斷每個貨物的不相容貨物是否出現在這組貨物中
            for (int j = 0; j < incompatible[goods[i]].size(); j++){
                if (contained[incompatible[goods[i]][j]]){
                    isYes = false;
                    break;
                }
            }
        }

        // 輸出結果
        if (isYes)
            printf("Yes\n");
        else
            printf("No\n");
    }

    return 0;
}

參考連結

https://blog.csdn.net/liuchuo/article/details/82560836


作者:@臭鹹魚

轉載請註明出處:https://www.cnblogs.com/chouxianyu/

歡迎討論和交流!