計蒜客模擬賽(五)第九題

計蒜客模擬賽第九題


在一個 n×m 的方格地圖上,某些方格上放置着炸彈。手動引爆一個炸彈以後,炸彈會把炸彈所在的行和列上的所有炸彈引爆,被引爆的炸彈又能引爆其他炸彈,這樣連鎖下去。

題目
現在爲了引爆地圖上的所有炸彈,需要手動引爆其中一些炸彈,爲了把危險程度降到最低,請算出最少手動引爆多少個炸彈可以把地圖上的所有炸彈引爆。
輸入格式
第一行輸兩個整數 n, m,用空格隔開。
接下來 n 行,每行輸入一個長度爲 m 的字符串,表示地圖信息。0表示沒有炸彈,1表示炸彈。
數據約定:
對於60% 的數據: 1≤n,m≤100;
對於 100% 的數據: 1≤n,m≤1000;
數據量比較大,不建議用cin輸入。
輸出格式
輸出要手動引爆的炸彈數。結論


分析

1.看到這道題我的思路是首先我需要確定炸彈的個數,以及每個炸彈所對應的座標,由於用到橫縱座標兩個參數,所以考慮決定選用結構體構建炸彈的點.
2.根據題目給定的要求需要以字符串,所以決定採用字符數組更爲合理,char類型,即輸入採用二維數組,根據所給定的m,n進行。
3.對於每一顆炸彈,他均有兩個參數,分別是行號和列號,對於所有的炸彈遍歷我們將按照,橫縱座標任意一個值相同我們將他們連接起來,然後我們將炸彈形成連通圖
題目要求
4.對於不同的炸彈不同的老大大大哥,所以將這些炸彈的大哥哥,放入棧內,最後去重,得到的vector長度即爲最終的最優答案


代碼實現

#include<iostream>
#include<vector>
#include<algorithm>
#include<string>
using namespace std;//首先記錄  炸彈即 1  存在的位置座標
#define Max 1000

char a[Max][Max];//每行可以容納的數量
int pre[Max];
int k = 0;

struct Node
{
    int x;
    int y;
}p[100];//100個炸彈點

int find(int x)
{
    int r = x;
    while (r != pre[r])
        r = pre[r];

    int i = x, j;
    while (i != r)//路徑壓縮
    {
        j = pre[i]; // 在改變上級之前用臨時變量  j 記錄下他的值 
        pre[i] = r; //把上級改爲根節點
        i = j;
    }
    return r;
}

int main()
{

    vector<int> elem;
    int n, m;
    cin >> n >> m;
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < m; j++)
        {
            cin >> a[i][j];

            if (a[i][j] == '1')//記錄炸彈,並且統計炸彈的個數
            {
                k++;
                p[k].x = i;
                p[k].y = j;
            }
        }
    }
    //炸彈的初始化,設置他們的前驅結點均爲自己
    for (int i = 1; i <= k; i++)
    {
        pre[i] = i;
    }
    //如果任意兩個炸彈的  橫或者縱座標相同則連接兩個點
    for (int i = 1; i <= k; i++)
    {
        for (int j = i + 1; j <= k; j++)
        {
            if (p[i].x == p[j].x || p[i].x == p[j].y)
            {
                pre[j] = i;
            }
        }
    }
    //將每個炸彈的大大大哥找到,壓入棧內
    /*記錄每個1的座標然後對相同的座標進行爆破,行座標相同直接爆破,縱座標相同直接爆破*/
    for (int i = 1; i <= k; i++)
    {
        elem.push_back(find(i));
    }
    //排序
    sort(elem.begin(), elem.end());
    elem.erase(unique(elem.begin(), elem.end()),elem.end());//unique()函數將重複的元素放置在最後
    //erase將重複的第一個元素開始,到最後一個元素開始,全部擦除
    cout << elem.size() << endl;//數字的種類既是最終的答案
    /*
    for (int i = 1; i <= k; i++)//前驅驗證
    {
        cout << "第" << i << "個的前驅" << pre[i] << endl;
    }*/
    /*得到最終的炸彈個數*/
    //cout << k << endl;

    return 0;
}

歡迎大家與我交流,並提出意見和建議,我將進行進一步優化和處理

發佈了56 篇原創文章 · 獲贊 82 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章