在乙個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##
樣例解釋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) }
int main()
} }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 輸出一行...