当前位置:网站首页>HDU1561 树形背包dp+边界优化 0ms过题
HDU1561 树形背包dp+边界优化 0ms过题
2022-08-02 14:26:00 【Shanhj】
对比网上各种版本的代码,主要优化为减少了无用计算,从原来的75ms降低至0ms
优化细节见代码注释
#include <bits/stdc++.h>
#define mem(a, v) memset(a, v, sizeof(a))
const int N = 205;
using namespace std;
struct edge
{
int to, next;
} e[N];
int head[N], ecnt;
void add(int u, int v) {
e[++ecnt].next = head[u], e[ecnt].to = v, head[u] = ecnt; }
int n, m, sz[N]; // sz[i]记录结点i的子结点数
int dp[N][N], val[N];
void einit(int n)
{
ecnt = 0;
for (int i = 0; i <= n; i++)
head[i] = 0;
}
void getsize(int u) //计算子结点数
{
sz[u] = 1;
for (int i = head[u]; i; i = e[i].next)
{
getsize(e[i].to);
sz[u] += sz[e[i].to];
}
}
void dfs(int u, int M) // M是当前层最多能攻取的城堡数,每递归一层就减一
{
dp[u][1] = val[u];
int v, szcnt = 1;
for (int i = min(sz[u], M); i >= 2; i--)
dp[u][i] = 0;
for (int i = head[u]; i; i = e[i].next)
{
v = e[i].to;
dfs(v, M - 1);
szcnt += sz[v]; // szcnt是当前子结点的数量和,用于确定j的边界
for (int j = min(szcnt, M); j >= 2; j--) //从大的往小推,否则会出现包含关系
{
//要保证v之前的结点数之和要不小于j-k,否则解不存在
int k1 = max(sz[v] + j - szcnt, 1);
//同时k不能超过j-1或sz[v]
int k2 = min(sz[v], j - 1);
for (int k = k1; k <= k2; k++) //从结点v攻取k个城堡
dp[u][j] = max(dp[u][j], dp[u][j - k] + dp[v][k]);
}
}
}
signed main()
{
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
int a;
val[0] = 0;
for (int i = 0; i < N; i++)
dp[i][0] = 0;
while (cin >> n >> m && n && m)
{
einit(n + 1);
m++;
for (int i = 1; i <= n; i++)
{
cin >> a >> val[i];
add(a, i);
}
getsize(0);
dfs(0, m);
cout << dp[0][m] << "\n";
}
return 0;
}
边栏推荐
猜你喜欢
随机推荐
Redis的5中数据类型总结
【故障诊断】基于PSO_VMD_MCKD方法的风机轴承微弱故障诊断
FIR滤波器设计之窗函数法
自定义属性
web渗透之sql注入
ELK日志分析系统
2022-07-23 第六小组 瞒春 学习笔记
DOM - Element Box Model
什么是Nacos?
PAT甲级 1143 最低公共祖先
Redis最新6.27安装配置笔记及安装和常用命令快速上手复习指南
二、QT界面开发--新建C语言工程
一文让你快速写上扫雷游戏!童年的经典游戏,发给你的小女友让你装一波!!
一文让你快速手写C语言-三子棋游戏
【数据知多少】一文学懂通过Tushare、AKshare、baostock、Ashare、Pytdx获取股票行情数据(含代码)
只出现一次的数字||| —— 哈希映射、异或位运算+分治思想
为什么四个字节的float表示的范围比八个字节的long要广?
中国服装行业已形成一套完整的产业体系
第三章-函数的增长-3.1-渐近记号
为什么四个字节的float表示的范围比八个字节的long要广?









