【GDOI三校联考】炸弹 题解
Description
在一个N行M列的二维网格里,有些格子是空地(用字符‘.’表示),有些格子是障碍物(用字符‘#’表示)。每个空地格子都有一只虫子,虫子不会移动。FJ打算用最少的炸弹把所有的虫子消灭。FJ每次可以选择在一个空地格子(不妨假设是格子a)放置一个炸弹,这个炸弹爆炸后,格子a的虫子会被消灭,假设有另一个空地格子b,如果空地格子b同时满足如下两个条件,那么空地b格子的虫子也会被该炸弹消灭:
1.格子a和格子b在同一行或者在同一列。
2.格子a和格子b之间没有障碍物格子。
有趣的是,任意两个不同的空地格子都有且只有一条由空地格子构成的路径,即所有空地格子构成一棵树形结构。注意:炸弹并不能毁灭障碍物!
Input
第一行,两个整数,n和m。1 <= n, m<=50。
接下来是n行m列的二维网格。
Sample Input
输入1:
3 4
#…
…##
#.##
输入2:
3 7
.#.#.#.
…
.#.#.#.
Output
输出最少的炸弹数。
Sample Output
输出1:
2
输出2:
4
分析
因为题目说空地形成一颗可爱的小树,所以我们很容易 想到树形DP,但是要怎么建树呢?我们考虑把一个只能延伸向一个方向的点作为根节点。以样例1为例
就是把某个点可以炸到的点都变成那个点的儿子。
然后考虑DP
我们设 f x , 0 f_{x,0} fx,0 f x , 1 f_{x,1} fx,1 f x , 2 f_{x,2} fx,2分别表示当前点没被炸到,没放炸弹但被炸到,放了炸弹三种状态,接着我们考虑转移。
f [ x ] [ 0 ] = ∑ f [ s o n ] [ 1 ] f[x][0]=\sum f[son][1] f[x][0]=∑f[son][1]
f [ x ] [ 1 ] = m i n ( f [ p ] [ 2 ] + ∑ m i n ( f [ s o n ] [ 0 ] , f [ s o n ] [ 1 ] , f [ s o n ] [ 2 ] ) ) f[x][1]=min(f[p][2]+\sum min(f[son][0],f[son][1],f[son][2])) f[x][1]=min(f[p][2]+∑min(f[son][0],f[son][1],f[son][2]))