按照 250 -> 1000 -> 550… 的顺序开的题。。
结果 1000 没撸出来 250 又挂了果断爆了 0 。。(但是居然 Unrate 了我会乱说 .. ??。。)
。。。言归正传。。
Brief description:
550:
…
1000:
给定一颗树状迷宫,定义一次染色操作为:每次覆盖一格点,同时覆盖其上下左右四个方向所有可以延伸到的其它格点。
问至少进行多少次操作可完成染色。
(.. . N ≤ 50 .. )
Analysis:
… 现场生算法:对每个转角位置建点,若两个转角位置通过路径相连则连边。。。
。。于是转化成一个变形的支配集问题。。(点集支配边集。。)。。
(于是这个方法还有待研究。。。)
第二种方法是对每条横竖边分离,根据转角位置连边。。转换成二分图边覆盖问题。。
。。但是有一些奇怪的树状数据这种方法会错。。。
。。。看来这种建模方法好像会丢拓扑信息。。(。。我试图贪心修正。。但看起来这种方法已经没救了。。)
。。于是对每个孤立的格点分别建点。。进行裸的动态规划。。
然后类比树的支配集问题,将状态分以下三类。。。
const int None = 0, Cover = 1, Extend = 2; // 还未被覆盖... 被覆盖但不可延伸 ... 被覆盖且可延伸...
之后枚举插头形状分情况讨论状态转移 或 做树上背包即可。。状态转移请看下图。。问号地区请自行脑补。。
-/0/1 ? 0 ? // None -/1 ? 1 ? // Cover 2 ? 2 ? // Extend x x 2 x // Guard
额。。下面以第三副图举例,要求正前方区域必须是 Extend,
同时左右两边要能安全覆盖,要不然是有一个 Extend,要不然是两面都是 Cover 。。。
具体书写的时候用 Delta 存一个差值。。和树的支配集的方法一样。。
另外值得注意的是,对于根结点需要默认一个正方向。
const int dx[] = {1, -1, 0, 0};
const int dy[] = {0, 0, 1, -1};
const int N = 50, NN = N * N;
bool Grid[N][N]; int dp[3][N][N];
int n, m;
inline int _R(int d){
return d ^ 1;
}
inline int inGrid(int x, int y){
return x >= 0 && x < n && y >= 0 && y < m;
}
inline bool legal(int x, int y){
return inGrid(x, y) && Grid[x][y];
}
#define u0 dp[0][x][y]
#define u1 dp[1][x][y]
#define u2 dp[2][x][y]
#define v0 dp[0][xx][yy]
#define v1 dp[1][xx][yy]
#define v2 dp[2][xx][yy]
#define v12 min(v1, v2)
#define v012 min(v0, v12)
void dfs(int x, int y, int dir){
int c_ = 0, c0 = INF, c1 = INF, c2 = INF;
int s1 = 0, s12 = 0, s012 = 0, delta = INF, guard = 1;
bool leaf = true; REP(i, 4){
if (_R(i) == dir) continue;
int xx = x + dx[i], yy = y + dy[i];
if (legal(xx, yy)){
dfs(xx, yy, i); if (i == dir || dir == -1 && i <= 1) c_ = INF, c0 = v0, c1 = v1, c2 = v2;
else s1 += v1, s12 += v12, s012 += v012, checkMin(delta, v2 - v012);
guard += v012, leaf = false;
}
}
if (leaf) u0 = 0, u1 = INF, u2 = 1;
else {
s012 += delta, u0 = min(c_, c0, c1) + min(s1, s012), u1 = min(c_, c1) + s012;
u2 = min(c2 + min(s1, s012), guard);
}
}
class FoxBomb {
public:
int getMinimumCost(vector <string> grid){
n = SZ(grid), m = SZ(grid[0]); int x0 = -1, y0;
REP_2(i, j, n, m) Grid[i][j] = grid[i][j] == '.';
REP_2(x, y, n, m) if (Grid[x][y]) REP(d, 4){
int xx = x + dx[d], yy = y + dy[d];
if (legal(xx, yy)) x0 = xx, y0 = yy;
}
dfs(x0, y0, -1);
return min(dp[1][x0][y0], dp[2][x0][y0]);
}
};




Alca
Amber
Belleve Invis
Chensiting123
Edward_mj
Fotile96
Hlworld
Kuangbin
Liyaos
Lwins
LYPenny
Mato 完整版
Mikeni2006
Mzry
Nagatsuki
Neko13
Oneplus
Rukata
Seter
Sevenkplus
Sevenzero
Shirleycrow
Vfleaking
wangzhpp
Watashi
WJMZBMR
Wywcgs
XadillaX
Yangzhe
三途川玉子
About.me
Vijos

250 爆搜没退出 50!的飘过
轻拍~。。
再次回访膜拜大牛,各种围观,各种ORZ /$:~_~