随笔分类 - 算法入门经典第二版第九章 动态规划初步
摘要:n的规模可以状压,f[x][y][S]表示x行,y列,S集合的巧克力能否被切割。预处理出每个状态S对应的面积和sum(S),对于一个合法的状态一定满足x*y=sum(S),实际上只有两个变量是独立的。而且有x,y等效与y,x,那么这里取max(x,y)。转移的时候枚举S的非空真子集,横着切或者竖着切...
阅读全文
摘要:状压dp,每个状态可以表示为一个n元组,且上限为8,可以用一个九进制来表示状态。但是这样做用数组开不下,用map离散会T。而实际上很多九进制数很多都是用不上的。因此类似uva 1601 Morning after holloween的思想,先dfs预处理出所有状态,用map将状态离散,预处理出算出状...
阅读全文
摘要:状压dp,用s表示已经询问过的特征,a表示W具有的特征。当满足条件的物体只有一个的时候就不用再猜测了。对于满足条件的物体个数可以预处理出来转移的时候应该枚举询问的k,因为实际上要猜的物品是不确定的,要么k是W所具有的,要么k不是W所具有的,要保证能猜到那么就应该取最坏情况下的最小值,所以有转移方程:...
阅读全文
摘要:题目:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=20&page=show_problem&problem=1758状态压缩的DP,dp[i][st]表示状态为st考虑后面i个人所有人最...
阅读全文
摘要:求一棵数的最大独立集结点个数并判断方案是否唯一。dp[i][j]表示以i为根的子树的最大独立集,j的取值为选和不选。决策:当选择i时,就不能选择它的子结点。当不选i时,它的子结点可选可不选。判断唯一性:当选择的某个子节点方案不唯一,父节点的方案就不唯一,或者某个子节点选或不选方案数一样。转移顺序:按...
阅读全文
摘要:区间dp,切割dp[i][j]的花费和切法无关(无后效性)dp[i][j]表示区间i,j的花费,于是只要枚举切割方法就行了,区间就划分成更小的区间了。O(n^3)四边形不等式尚待学习#include //变量不要取成ignore left之类using namespace std;const int...
阅读全文
摘要:dp[i][j]表示前一个序列拿了i个颜色,后一个序列拿了j个颜色的最小花费。转移的时候显然只能向dp[i+1][j],或dp[i][j+1]转移,每增加拿走一个颜色,之前已经出现但没结束的颜色个数的跨度都增加1,为了在转移的时候快速算出这个值,先预处理出每个颜色在各个序列中的起始和终止位置。mem...
阅读全文
摘要:坑,一开始以为,分成两半的时候去最大那个就行了,实际上这样是不对的,因为有可能出现小的一半的时间比大的要长,因为还和等待次数有关,且转移的时候需要用到次数更小的状态,所以状态定义为二维,dp[i][j]表示长度为i的区间,放小于等于j次的概率。要求确切的某次的概率,比如k,就只要用dp[i][k]-...
阅读全文
摘要:首先是一个贪心,一种灯泡要么全都换,要么全都不换。先排序,定义状态d[i]为前面i种灯泡的最小花费,状态转移就是从d[j],jusing namespace std;const int maxn = 1e3+3;int V[maxn], K[maxn], C[maxn], L[maxn];int d...
阅读全文
摘要:d[i]表示前面i个字符划分成的最小回文串个数,转移:当第i字符加进来和前面区间j构成回文串,那么d[i] = d[j]+1。要判断前面的字符j+1到i是不是回文串,可以用Manacher算法预处理出来。(其实O(n^2)判断回文串的也可以,时间复杂度不会变,只是为了学习ManacherManach...
阅读全文
摘要:每首只能唱一次,而且中间不能不唱歌,所以先把状态赋值为-1,以区别合法状态和非法状态,在唱歌曲目最多的条件下,离开时间应该尽量晚。状态定义f[i][j]考虑前i首歌唱歌时间为j的最大唱歌曲目#includeusing namespace std;const int maxn = 55;const i...
阅读全文
摘要:分阶段的DAG,注意字典序的处理和路径的保存。定义状态d[i][j]为从i,j 出发到最后一列的最小花费,转移的时候只有三种,向上,向下,或平移。#includeusing namespace std;const int maxm = 11;const int maxn = 101;int G[ma...
阅读全文
摘要:TSP是NP难,但是把问题简化,到最右点之前的巡游路线只能严格向右,到最右边的点以后,返回的时候严格向左,这个问题就可以在多项式时间内求出来了。定义状态d[i][j]表示一个人在i号点,令一个人在j号点,之前的点全走过到终点还要走的最小长度,为了区别d[i][j]和d[j][i]规定i>j,然后考虑...
阅读全文
摘要:据说是DAG的dp,可用spfa来做,松弛操作改成变长。注意状态的表示。影响决策的只有顶部的尺寸,因为尺寸可能很大,所以用立方体的编号和高的编号来表示,然后向尺寸更小的转移就行了。#includeusing namespace std;#define MP make_pair#define fi f...
阅读全文