思路
状态计算
题目
注意:
- 那个人可以从矩形网格滑雪场的任意一点出发,可以上下左右移动
- 每次只能滑一个单位距离
- 这个人能够滑动到某相邻区域的前提是该区域的高度低于自己目前所在区域的高度
代码
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
const int N = 6010;
vector<int> g[N]; //用g来存储边之间的关系
int n, happy[N]; //表示第i个人的欢乐值
int f[N][2] ; //表示状态
int root;
int has_father[N]; //标记每个点的父节点,以确定根节点是谁
//在dfs时可以确定父子关系,但是这道题更简单直接就确定了,父子关系
//开这个数组的原因:当n - 1条边输入结束的时候,只有根节点对应的has_father[root]为0,目的就是为了求出根节点
void dfs(int u)
{
int sz = g[u].size();
f[u][1] = happy[u];
for (int i = 0; i < sz; i ++)
{
int v = g[u][i];
dfs(v);
f[u][0] += max(f[v][0], f[v][1]);
f[u][1] += f[v][0];
}
}
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i ++) scanf("%d", &happy[i]);
for (int i = 1; i <= n - 1; i ++)
{
int a, b;
scanf("%d%d", &a, &b); //a的父节点是b
has_father[a] = b; // 将a的父节点标记为b
g[b].push_back(a); //因为a是b的子节点,相当于将一条边终点是a放到了g[b]中去,相当于用邻接表存储边
}
for (int i = 1; i < n; i ++) //确定根节点
{
if (!has_father[i]) //只有has_father = 0,也就是没有根节点此时输出
{
root = i;
break;
}
}
dfs(root);
printf("%d\n", max(f[root][0], f[root][1]));
return 0;
}
注意
f[][]
二维数组初始化的时候最好统一赋值为-1,如果不进行初始化直接用0判断,此题可以,可是如果遇到一些记忆化搜索的问题要求方案数的时候,初始化是0可能会导致个别情况计算出来的恰好结果是0时,却被认为未遍历过,因此统一赋值为-1就没错了