zoukankan      html  css  js  c++  java
  • 引爆炸弹——DFS&&联通块

    题目

    链接

    在一个$n imes m$方格地图上,某些方格上放置着炸弹。手动引爆一个炸弹以后,炸弹会把炸弹所在的行和列上的所有炸弹引爆,被引爆的炸弹又能引爆其他炸弹,这样连锁下去。

    现在为了引爆地图上的所有炸弹,需要手动引爆其中一些炸弹,为了把危险程度降到最低,请算出最少手动引爆多少个炸弹可以把地图上的所有炸弹引爆。

    解决方案

    由于炸弹连锁,问题等价于求图中的联通块,只是此处的不只是相邻的炸弹联通,同行或同列也是广义的联通。

    值得注意的是,寻找“相邻”炸弹时不能挨个查找(会超时),需要先预处理每个炸弹的“东”、“西”、“南”、“北”相邻炸弹的位置。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 
     4 const int maxn = 1000 + 10;
     5 const int maxm = 1000 + 10;
     6 int n,m;
     7 bool maze[maxn][maxm];
     8 bool r[maxn], c[maxm];
     9 char s[maxm];
    10 int dn[maxn][maxm], ds[maxn][maxm], dw[maxn][maxm], de[maxn][maxm];
    11 
    12 void init()
    13 {
    14     //memset(dn, -1, sizeof(dn));
    15     //memset(ds, -1, sizeof(ds));
    16     //memset(dw, -1, sizeof(dw));
    17     //memset(de, -1, sizeof(de));
    18     for(int j = 0;j < m;j++)
    19     {
    20         int flagn = -1;
    21         for(int i = 0;i < n;i++)
    22         {
    23             dn[i][j] = flagn;
    24             if(maze[i][j] == 1)  flagn = i;
    25         }
    26     }
    27 
    28     for(int j = 0;j < m;j++)
    29     {
    30         int flags = -1;
    31         for(int i = n-1;i >= 0;i--)
    32         {
    33             ds[i][j] = flags;
    34             if(maze[i][j] == 1)  flags = i;
    35         }
    36     }
    37 
    38     for(int i = 0;i < n;i++)
    39     {
    40         int flagw = -1;
    41         for(int j = 0;j < m;j++)
    42         {
    43             dw[i][j] = flagw;
    44             if(maze[i][j] == 1)  flagw = j;
    45         }
    46     }
    47 
    48     for(int i = 0;i < n;i++)
    49     {
    50         int flage = -1;
    51         for(int j = m - 1;j >= 0;j--)
    52         {
    53             de[i][j] = flage;
    54             if(maze[i][j] == 1)  flage = j;
    55         }
    56     }
    57 }
    58 
    59 int cnt = 0;
    60 void dfs(int i, int j)
    61 {
    62     //printf("%d %d
    ", i, j);
    63     maze[i][j] = 0;
    64     r[i] = c[j] = true;
    65 
    66     if(dn[i][j] != -1 && maze[dn[i][j]][j] == 1)  dfs(dn[i][j], j);
    67     if(ds[i][j] != -1 && maze[ds[i][j]][j] == 1)  dfs(ds[i][j], j);
    68     if(dw[i][j] != -1 && maze[i][dw[i][j]] == 1)  dfs(i, dw[i][j]);
    69     if(de[i][j] != -1 && maze[i][de[i][j]] == 1)  dfs(i, de[i][j]);
    70 
    71 }
    72 
    73 
    74 int main()
    75 {
    76     scanf("%d%d", &n,&m);
    77     for(int i = 0;i < n;i++)
    78     {
    79         scanf("%s", s);
    80         for(int j = 0;j < m;j++)  maze[i][j] = s[j] - '0';
    81     }
    82 
    83     init();
    84 
    85     int ans = 0;
    86     for(int i = 0;i <n;i++)
    87         for(int j = 0;j < m;j++)
    88         {
    89             if(maze[i][j] == 1 && (!r[i]) && (!c[j]))  //出现过的行和列肯定不可能再存在“未爆炸”的炸弹
    90             {
    91                 dfs(i, j);
    92                 ans++;
    93             }
    94         }
    95     printf("%d
    ", ans);
    96 
    97     return 0;
    98 }
  • 相关阅读:
    ZOJ 3818 Pretty Poem
    HDU 4597 Play Game
    HDU 4497 GCD and LCM
    CSU 1335 高桥和低桥
    UVA 10791 Minimum Sum LCM
    CSU 1119 Collecting Coins
    CSU 1120 病毒
    UVA 12169 Disgruntled Judge
    HDU 1301 Jungle Roads
    POJ 1258 Agri-Net
  • 原文地址:https://www.cnblogs.com/lfri/p/11134915.html
Copyright © 2011-2022 走看看