热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

寒假:Day4

Day4今天继续复习搞基础课,加油!树形DP每一个节点都分为选和不选两种状态,选为f[i,1],不选为f[i,0]&#
Day4

今天继续复习搞基础课,加油!

树形DP

每一个节点都分为选和不选两种状态,选为f[i, 1],不选为f[i, 0],每一个节点想要最大,他的每一个子树权值都必须最大,递归即可

不选择根节点的最大值:
f[i,0]=max(f[s1,0],f[s1,1])+max(f[s2,0],f[s2,1])+...+max(f[sk,0],f[sk,1])f[i, 0] = max(f[s1, 0], f[s1, 1]) + max(f[s2, 0], f[s2, 1]) +...+ max(f[sk, 0], f[sk, 1]) f[i,0]=max(f[s1,0],f[s1,1])+max(f[s2,0],f[s2,1])+...+max(f[sk,0],f[sk,1])
选择根节点的最大值:
f[i,1]=f[s1,0]+f[s2,0]+f[s3,0]+.....+f[sk,0]f[i, 1] = f[s1, 0] + f[s2, 0] + f[s3, 0] + ..... + f[sk, 0] f[i,1]=f[s1,0]+f[s2,0]+f[s3,0]+.....+f[sk,0]
AcWing 285. 没有上司的舞会 - AcWing

#include
using namespace std;
const int N = 6010;
int n;
int w[N];
int h[N], e[N], ne[N], idx;
bool st[N]; // 用来判断是否有父节点,查找根节点
int f[N][2];void add(int a, int b)
{e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}void dfs(int u){f[u][1] = w[u];for (int i = h[u]; i != -1; i = ne[i]) { int j = e[i];dfs(j);f[u][0] += max(f[j][0], f[j][1]); // 状态转移f[u][1] += f[j][0];}
}int main(void)
{cin >> n ;for (int i &#61; 1 ; i <&#61; n ; i &#43;&#43;) cin >> w[i];memset(h, -1, sizeof h);for (int i &#61; 0; i < n - 1; i&#43;&#43;) {int a, b ;cin >> a >> b ;add(b, a);st[a] &#61; true;}int root &#61; 1;while (st[root]) root&#43;&#43;; //找到根节点dfs(root);cout << max(f[root][0], f[root][1]) << endl ;return 0;
}

记忆化搜索

顾名思义&#xff0c;就是把每一次搜索的过程中的有用信息都存下来&#xff0c;这样下一次搜索如果也要用到这个信息&#xff0c;就可以直接调用而不用再次搜索

AcWing 901. 滑雪 - AcWing

#include
using namespace std;const int N &#61; 310;
int n, m;
int h[N][N];
int f[N][N];int dx[] &#61; {-1, 0, 1, 0};
int dy[] &#61; {0, 1, 0, -1};int dp(int x, int y)
{int &v &#61; f[x][y]; // v 等价于 f[x][y]if (v !&#61; -1) return v; // 如果他已经被搜过了&#xff0c;直接返回值v &#61; 1; // 至少为1for (int i &#61; 0; i < 4; i&#43;&#43;) {int a &#61; x &#43; dx[i], b &#61; y &#43; dy[i];if (a >&#61; 1 && a <&#61; n && b >&#61; 1 && b <&#61; m && h[a][b] < h[x][y])v &#61; max(v, dp(a, b) &#43; 1);}return v;
}int main(void)
{scanf("%d %d", &n, &m);for (int i &#61; 1; i <&#61; n; i&#43;&#43;) {for (int j &#61; 1; j <&#61; m; j&#43;&#43;) {scanf("%d", &h[i][j]);}}memset(f, -1, sizeof f); // 表示每个状态都没有被算过int res &#61; 0;for (int i &#61; 1; i <&#61; n; i&#43;&#43;) {for (int j &#61; 1; j <&#61; m; j&#43;&#43;) {res &#61; max(res, dp(i, j));}}cout << res << endl ;return 0;
}

区间DP

区间dp &#xff0c;指在一段区间上进行动态规划&#xff0c;一般做法是由长度较小的区间往长度较大的区间进行递推&#xff0c;最终得到整个区间的答案&#xff0c;而边界就是长度为1以及2的区间。

282. 石子合并 - AcWing题库

#include
using namespace std;
const int N &#61; 310;
int n;
int s[N]; // 前缀和
int f[N][N];int main(void)
{cin >> n;for (int i &#61; 1; i <&#61; n; i&#43;&#43;) cin >> s[i], s[i] &#43;&#61; s[i - 1]; // 前缀和for (int len &#61; 2; len <&#61; n; len&#43;&#43;) { // 先枚举区间长度for (int i &#61; 1; i &#43; len - 1 <&#61; n; i&#43;&#43;) { // 再枚举区间左端点int j &#61; i &#43; len - 1;f[i][j] &#61; 1e8;for (int k &#61; i; k < j; k&#43;&#43;) { // 枚举区间内每一种合并方式求最小f[i][j] &#61; min(f[i][j], f[i][k] &#43; f[k &#43; 1][j] &#43; s[j] - s[i - 1]);}}}cout << f[1][n] << endl ;return 0;
}

计数DP

类比完全背包问题&#xff0c;前i个物品中任选且体积恰好为j的方案数f[i, j]&#xff0c;对第i个物品进行分集合&#xff0c;选一个第i个物品使得体积恰好为j就是f[i, j - i]&#xff0c;选两个第i个物品使得体积恰好为j就是f[i, j - 2i]&#xff0c;以此类推方案数就是总和
f[i,j]&#61;f[i−1,j]&#43;f[i,j−i]&#43;f[i,j−2∗i]&#43;f[i,j−3∗i]&#43;...&#43;f[i,j−s∗i]f[i, j] &#61; f[i - 1, j] &#43; f[i, j - i] &#43; f[i, j - 2 * i] &#43; f[i, j - 3 * i] &#43; ... &#43; f[i, j - s * i] f[i,j]&#61;f[i1,j]&#43;f[i,ji]&#43;f[i,j2i]&#43;f[i,j3i]&#43;...&#43;f[i,jsi]
利用完全背包优化方式&#xff1a;
f[i,j−i]&#61;f[i−1,j−i]&#43;f[i,j−2∗i]&#43;f[i,j−3∗i]&#43;...&#43;f[i,j−s∗i]f[i, j - i] &#61; f[i - 1, j - i] &#43; f[i, j - 2 * i] &#43; f[i, j - 3 * i] &#43; ... &#43;f[i, j - s * i] f[i,ji]&#61;f[i1,ji]&#43;f[i,j2i]&#43;f[i,j3i]&#43;...&#43;f[i,jsi]
可得&#xff1a;f[i,j]&#61;f[i−1,j]&#43;f[i,j−i]​f[i, j] &#61; f[i - 1, j] &#43; f[i, j - i]​f[i,j]&#61;f[i1,j]&#43;f[i,ji]

然后优化成一维空间&#xff0c;变成f[j]&#61;f[j]&#43;f[j−i]f[j] &#61; f[j] &#43; f[j - i]f[j]&#61;f[j]&#43;f[ji]即可

AcWing 900. 整数划分 - AcWing

#include
using namespace std;
const int N &#61; 1010, mod &#61; 1e9 &#43; 7;
int f[N];
int main(void)
{int n;cin >> n;f[0] &#61; 1;for (int i &#61; 1; i <&#61; n; i&#43;&#43;) {for (int j &#61; i; j <&#61; n; j&#43;&#43;) {f[j] &#61; (f[j] &#43; f[j - i]) % mod;}}cout << f[n] << endl ;return 0;
}


推荐阅读
  • UVa 11683: 激光雕刻技术解析
    自1958年发明以来,激光技术已在众多领域得到广泛应用,包括电子设备、医疗手术工具、武器等。本文将探讨如何使用激光技术进行材料雕刻,并通过编程解决一个具体的激光雕刻问题。 ... [详细]
  • 题目描述:Balala Power! 时间限制:4000/2000 MS (Java/Other) 内存限制:131072/131072 K (Java/Other)。题目背景及问题描述详见正文。 ... [详细]
  • 本文探讨了Linux环境下线程私有数据(Thread-Specific Data, TSD)的概念及其重要性,介绍了如何通过TSD技术避免多线程间全局变量冲突的问题,并提供了具体的实现方法和示例代码。 ... [详细]
  • HDU 2537 键盘输入处理
    题目描述了一个名叫Pirates的男孩想要开发一款键盘输入软件,遇到了大小写字母判断的问题。本文提供了该问题的解决方案及实现方法。 ... [详细]
  • 本文介绍了一种使用链剖分(Link-Cut Tree, LCT)来维护动态树结构的方法,特别是如何通过 LCT 来高效地管理子树的信息,如子树大小等。 ... [详细]
  • 在学习了Splay树的基本查找功能后,可能会觉得它与普通的二叉查找树没有太大的区别,仅仅是通过splay操作减少了时间开销。然而,Splay树之所以被誉为“序列之王”,主要在于其强大的区间操作能力。 ... [详细]
  • 本文针对HDU 1042 N! 问题提供详细的解析和代码实现。题目要求计算给定整数N(0 ≤ N ≤ 10000)的阶乘N!。文章不仅提供了算法思路,还附上了C++语言的具体实现。 ... [详细]
  • 本文介绍了使用Python和C语言编写程序来计算一个给定数值的平方根的方法。通过迭代算法,我们能够精确地得到所需的结果。 ... [详细]
  • 该问题描述了以不同价格购买三种类型的鸡(公鸡、母鸡和小鸡),使用100元恰好购买100只鸡的不同组合。具体而言,每只公鸡价值5元,每只母鸡价值3元,而每三只小鸡价值1元。问题是,如何用100元购买100只鸡,并找出所有可能的公鸡、母鸡和小鸡的组合。 ... [详细]
  • SSE图像算法优化系列三:超高速导向滤波实现过程纪要(欢迎挑战)
    自从何凯明提出导向滤波后,因为其算法的简单性和有效性,该算法得到了广泛的应用,以至于新版的matlab都将其作为标准自带的函数之一了&#x ... [详细]
  • 编程解析:CF989C 花朵之雾 (构造算法)
    本文深入探讨了CF989C '花朵之雾'问题的构造算法,提供了详细的解题思路和代码实现。 ... [详细]
  • 本文详细探讨了HihoCoder平台上的1398号问题——最大权闭合子图的求解方法。通过具体实例,深入分析了最大权闭合子图的概念及其算法实现。 ... [详细]
  • 探讨了一个包含纯虚函数的C++代码片段,分析了其中的语法错误及逻辑问题,并提出了修正方案。 ... [详细]
  • 本文详细介绍了在Luat OS中如何实现C与Lua的混合编程,包括在C环境中运行Lua脚本、封装可被Lua调用的C语言库,以及C与Lua之间的数据交互方法。 ... [详细]
  • 网络流24题——试题库问题
    题目描述:假设一个试题库中有n道试题。每道试题都标明了所属类别。同一道题可能有多个类别属性。现要从题库中抽取m道题组成试卷。并要求试卷包含指定类型的试题。试设计一个满足要求的组卷算 ... [详细]
author-avatar
PHPdudu
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有