炸弹 树形地图
来源:互联网 发布:大数据交易qtjiaoyi 编辑:程序博客网 时间:2024/06/13 19:19
题目大意:在一个50*50的地图内,有些是空地,另外的是障碍物,空地是连成一棵树。若在某空地放置一个炸弹,那么在同一列和同一行且没有障碍物阻拦的格子都被炸到(类似于泡泡堂。。。)。询问至少需要多少个炸弹才能把所有的格子都炸到。
题目中很关键的一个字眼就所有的空地是一棵树,这促使我们往树形动态规划的方面去想。
构建一棵二叉树,左子树表示在同一行的空地,右子树表示同一列的空地。那么,若把某个节点炸掉,受到影响的将会是它的父亲和祖先,左孩子和左孩子的左孩子,左孩子的左孩子的左孩子,以及右孩子,右孩子的右孩子....。对每个点记录两个状态,一个是该节点被炸以后,有一个向左上的威力把父亲炸掉,以及有一个右上的威力把父亲炸掉。
#include <cstdio>#include <cstdlib>#include <cmath>#include <cstring>#include <iostream>#include <algorithm>#include <queue>#include <map>#include <set>using namespace std;#define st first#define nd second#define pi 3.141592653589793238462643383const int dx[4] = {0, 0, 1, -1};const int dy[4] = {1, -1, 0, 0};const int inf = 0x3f3f3f3f;#define Rep(i, n) for (int i = 0, _n = n; i < _n; i ++)#define Repp(i, n) for (int i = 1, _n = n; i <= _n; i ++)#define For(i, a, b) for (int i = a, _b = b; i <= _b; i ++)#define Forr(i, a, b) for (int i = a, _b = b; i >= _b; i --)typedef long long ll;typedef pair<int, int> pii;#define maxn 57#define maxp maxn*maxnint n, m, sx, sy;int dat[maxn][maxn];struct Pointer{ Pointer *lc, *rc; int lf, rf; int get() { return min(lf, rf); }}head[maxp], *nll = head;void Init() { scanf("%d%d\n", &n, &m); nll -> lf = nll -> rf = 0; int cnt = 0; char ch; Repp(i, n) { Repp(j, m) { scanf("%c", &ch); if (ch == '.') { // 编号 dat[i][j] = ++ cnt; head[cnt].lc = head[cnt].rc = nll; if (cnt == 1) sx = i, sy = j; } } scanf("\n"); }}void dfs(Pointer *x) { if (x == nll) return; dfs(x -> lc); dfs(x -> rc); if (x -> rc != nll) x -> lf = x -> rc -> lf + x -> lc -> get(); else x -> lf = inf; if (x -> lc != nll) x -> rf = x -> lc -> rf + x -> rc -> get(); else x -> rf = inf; // 其实这里可以多记录两个部分和,那么不用每次往下找一次 // 时间复杂度从 O(n ^ 3) 降到 O(n ^ 2) int tmp = 1; Pointer *p = x; while (true) { p = p -> lc; if (p == nll) break; tmp += p -> rc -> get(); } p = x; while (true) { p = p -> rc; if (p == nll) break; tmp += p -> lc -> get(); } x -> lf = min(x -> lf, tmp); x -> rf = min(x -> rf, tmp);}pii que[maxp];// 构建二叉树 void Graph() { int quehead = 0, quetail = 0; que[0].st = sx, que[0].nd = sy; while (quehead <= quetail) { pii now = que[quehead ++]; Rep(k, 4) { pii to; to.st = now.st + dx[k]; to.nd = now.nd + dy[k]; if (dat[to.st][to.nd] > 0) { Pointer *p = &head[dat[now.st][now.nd]]; // 若已经有(左、右)孩子,则一直找(左、右)孩子的(左、右)孩子。 if (k < 2) { while (p -> lc != nll) p = p -> lc; p -> lc = &head[dat[to.st][to.nd]]; } else { while (p -> rc != nll) p = p -> rc; p -> rc = &head[dat[to.st][to.nd]]; } que[++ quetail] = to; } } dat[now.st][now.nd] = 0; }}int main() { freopen("bomb.in", "r", stdin); freopen("bomb.out", "w", stdout); Init(); Graph(); dfs(&head[1]); printf("%d\n", min(head[1].lf, head[1].rf)); return 0;}
- 炸弹 树形地图
- HDU5290树形DP一颗树扔炸弹几次能炸完
- 炸弹
- 炸弹
- 炸弹
- 炸弹
- 炸弹
- [BZOJ1017][JSOI2008][树形DP]魔兽地图DotR
- bzoj1017 [JSOI2008]魔兽地图DotR 树形DP
- 树形地图的A*寻路算法
- bzoj1017: [JSOI2008]魔兽地图DotR[树形DP+依赖型背包]
- 【East!模拟赛】【Round1】【BZOJ1017】魔兽地图Dotr 树形DP
- 【树形背包】【JSOI 2008】【bzoj 1017】魔兽地图DotR
- txt炸弹
- 网页炸弹
- 糖果炸弹
- google炸弹
- fork 炸弹
- upper_bound() 与 lower_bound() 使用方法
- MFC 显示本地HTML文件
- 函数指针作为某个函数的参数及定义函数指针
- 忆2012,希望有一个满意的2013
- 详解android如何创建和使用AVD
- 炸弹 树形地图
- Memcached相关技术收藏
- arcgis for android QueryTask的简单使用
- UVa-11235 - Frequent values
- 百度地图API学习总结
- 数据库启动初始化过程探讨
- glassfish创建连接池失败(Class name is wrong or classpath is not set for : com.mysql.jdbc.jdbc2.optional.My)
- HDU: 1247.Hat’s Words
- iOS学习无捷径