在乙個n行m列的二維網格裡,有些格仔是空地(用字元『.』表示),有些格仔是障礙物(用字元『#』表示)。每個空地格仔都有乙隻蟲子,蟲子不會移動。fj打算用最少的炸彈把所有的蟲子消滅。fj每次可以選擇在乙個空地格仔(不妨假設是格仔a)放置乙個炸彈,這個炸彈**後,格仔a的蟲子會被消滅,假設有另乙個空地格仔b,如果空地格仔b同時滿足如下兩個條件,那麼空地b格仔的蟲子也會被該炸彈消滅:
1.格仔a和格仔b在同一行或者在同一列。
2.格仔a和格仔b之間沒有障礙物格仔。
有趣的是,任意兩個不同的空地格仔都有且只有一條由空地格仔構成的路徑,即所有空地格仔構成一棵樹形結構。注意:炸彈並不能毀滅障礙物!
第一行,兩個整數,n和m。1 <= n, m<=50。
接下來是n行m列的二維網格。
輸出最少的炸彈數。
輸入1:
3 4#…
…###.##
輸入2:
3 7.#.#.#.
….#.#.#.
輸出1:
輸出2:
30%的資料滿足空地格仔數量小於20
hint
樣例解釋1:
#.b.
.b##
#.##
樣例解釋2:
.#.#.#.
b.b.b.b
.#.#.#.
字元b表示放置炸彈
看到樹形結構就開始往dp上想。
畫了半天的式子,發現狀態特別亂,主要是很難處理其炸彈延伸出去的情況。
然後想了個水法,由於只能放在拐角處,於是很「聰明」地打了個暴力,加了幾個剪枝。其實一點也不聰明。
%%%lyl大爺2年前就切了,而且方法及其巧妙。
此題難點主要在於狀態設定,lyl大爺的狀態就提供了個很好的思路。
由於是樹形結構,所以考慮樹形dp。先把樹建出來,然後類似於重鏈剖分一樣把樹按照橫縱方向確定一條條鏈。
現在就可以考慮轉移狀態:
那麼我們就可以愉快轉移了。
只需要分類討論當前節點有多少個兒子的情況,討論的情況數也多,可以自己搗鼓。當然也可以看標 (前提是你看得懂)
#include
#include
#include
#include
using
namespace std;
const
int maxn=
10010
;const
int inf=
1000000
;int fx[4]
[2]=
,,,}
;int n,m,ma[55]
[55],cnt,id[55]
[55];
int tot,nex[maxn*2]
,las[maxn*2]
,tov[maxn*2]
,ki[maxn*2]
;int f[maxn][3
],siz[maxn]
;char s[55]
;bool bz[maxn]
;int
min1
(int x,
int y,
int z)
void
insert
(int x,
int y,
int z)
void
dfs(
int x,
int ff,
int fw)
else}}
if(siz[x]==0
)else
if(siz[x]==1
)else
}else
if(siz[x]==2
)else
}else
if(siz[x]==3
)}intmain()
}}for(
int i=
1;i<=n;i++)}
}}}}
dfs(1,
0,1)
;printf
("%d\n"
,min
(f[1][
1],f[1][
2]))
;}
jzoj3252 GDOI三校聯考 炸彈
在乙個n行m列的二維網格裡,有些格仔是空地 用字元 表示 有些格仔是障礙物 用字元 表示 每個空地格仔都有乙隻蟲子,蟲子不會移動。fj打算用最少的炸彈把所有的蟲子消滅。fj每次可以選擇在乙個空地格仔 不妨假設是格仔a 放置乙個炸彈,這個炸彈 後,格仔a的蟲子會被消滅,假設有另乙個空地格仔b,如果空地...
JZOJ5242 GDOI模擬 矩陣
給出乙個n m 的01 矩陣,求其中有多少個連續子矩陣,使得其面積大於等於k,且其中不包含1。非常經典的一道題目。首先我們很容易知道n 3的方法。那麼我們來優化一下。我們先求出f i j 表示從 i,j 向右連續1的數量。然後把這些從大到小的插入 桶排一下 然後如果上面或下面已經有了就合併,然後算出...
JZOJ5242 GDOI2018模擬8 8 矩陣
description 給出乙個n m 的01 矩陣,求其中有多少個連續子矩陣,使得其面積大於等於k,且其中不包含1。input 第一行為用空格隔開的三個整數n,m,k。分別表示矩陣的行數,列數和子矩陣的最小面積。接下來的n 行每行為用空格隔開的m 個整數,為題目中給出的矩陣。output 輸出一行...