您的位置:首页 > 其它

BZOJ 1217: [HNOI2003]消防局的设立 贪心+dfs

2016-09-24 20:04 453 查看
BZOJ 1217: [HNOI2003]消防局的设立

在某背景下做了此题。此题有解为树形DP,这里是贪心的题解。

思路:考虑到 一个消防局可以扑灭与他距离 <= 2 的所有点。那么我们每隔4个点放一个消防局是最优的。

在 dfs 中:我们用数组 f[] 标记每个点 某种程度上可以说 abs(f[x]-5) 就是 x 到消防局的距离。当 f[x] == 5 时 那我们另 f[x] == 0 即,把这个看为一个消防局 ans ++;

还有一个地方就是处理一下边界,即开始的点,如果走到了这里而这里距离最近的消防局的距离大于等于3,也就是这里没有被消防局覆盖,那就只能在这里也加上一个消防局了。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;

const int MAXN = 1000 + 10;
int tot = 0, ans = 0;
int first[MAXN], nxt[MAXN << 1], f[MAXN];
struct edge{
int from, to;
}es[MAXN << 1];

void build(int ff, int tt)
{
es[++tot] = (edge){ff,tt};
nxt[tot] = first[ff];
first[ff] = tot;
}

void dfs(int x, int p = -1)
{
int maxn = -MAXN, minn = MAXN;
for(int i = first[x]; i != -1; i = nxt[i])
{
int v = es[i].to;
if(v != p)
{
dfs(v, x);
maxn = max(f[v], maxn);
minn = min(f[v], minn);
}
}
if(maxn + minn <= 3)
f[x] = minn + 1;
else f[x] = maxn + 1;
if(minn == MAXN)
f[x] = 3;
if(f[x] == 5)
{
ans ++;
f[x] = 0;
}
else if(p == -1 && f[x] >= 3)
ans ++;
}

int main()
{
int n;
cin >> n;
memset(first,-1,sizeof(first));
for(int i = 1; i < n; i ++)
{
int v;
scanf("%d",&v);
v --;
build(i,v);
build(v,i);
}
dfs(0);
cout << ans << endl;
return 0;
}


P.S 这种做法 是跟这个博客学的。尊重知识产权从我做起。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  dfs 贪心