DP动态规划
文章平均质量分 67
acraz
这个作者很懒,什么都没留下…
展开
-
FZU 2037 Maximum Value Problem
题目大意:给定一个大小为n的数列,元素各不相同且均大于0,现给定max=0;求对于所有该数列的排列,max一共需要更新几次,还要求出平均更新几次,即ans/(n!) 注意:分清楚什么时候%mod 思路:从n递推到n-1 对于一个大小为n的数列,其排列由两部分组成:1.最大值在最右端 2.最大值不再最右端 对于第一部分:ans1=ans[n-1]+(n-1)!; 对于第二部分:a原创 2015-05-17 16:17:44 · 333 阅读 · 0 评论 -
HDU 1712 ACboy needs your help(泛化物品dp)
背包九讲中的泛化物品,裸模板了。 #pragma warning(disable:4996) #include #include #include using namespace std; int a[105][105]; int ans[105]; int main(){ int n, m; while (scanf("%d %d", &n, &m)){ if (n == 0原创 2015-09-02 00:22:48 · 507 阅读 · 0 评论 -
2015.9.2组队赛 1006题(dp:前缀和优化,空间压缩)
题目描述 求有多少个数列满足a1+a2+a3+...+am=n, 0 输入描述 第一行是样例个数。(少于10000个样例) 每一个样例第一行有n,m(1 输出描述 每一个样例,输出答案mod 1000000007 输入 2 4 2 4 3 输出 1 0 思路:首先我们容易想到要想有一个数列满足条件,那么n>=(m*(m+1)/2)。所以我们只需要把m控制在sqrt(n)原创 2015-09-02 19:37:07 · 351 阅读 · 0 评论 -
POJ 1949 Chores(树形dp)
想来想去不知道怎么用拓扑,然后dp过了。 树形dp挺简单的,就是父节点完成的时刻是该节点所有的子节点完成时刻中的最大值加上父节点完成需要的时间(注意一下时刻跟时间)。然后一次水过去了。 #pragma warning(disable:4996) #include #include #include #include using namespace std; const int N =原创 2015-09-08 23:12:45 · 261 阅读 · 0 评论 -
POJ 1836 Alignment(DP最长上升子序列)
要注意理解好题意,题目让求数组a[1,...i]最长上升子序列长度加上a[i+1,...n]最长降低子序列长度的最大值,然后n-最大值就是答案。 方法就是正反用求两次最长上升子序列,然后用后缀mx[i]数组记录记录一下从a[i]开始的最长的降低子序列长度。就能O(n)的找出我们要的最大值。 #pragma warning(disable:4996) #include #include #i原创 2015-09-12 14:38:58 · 453 阅读 · 0 评论 -
POJ 2533 Longest Ordered Subsequence(DP最长上升子序列O(n^2)&&O(nlogn))
先说一下简单的O(n^2)的算法: dp[i]表示以a[i]结尾的最长上升子序列的长度。那么我们每次求dp[i]的时候都要扫一遍所有的a[j] 下面是代码 #pragma warning(disable:4996) #include #include #include using namespace std; int a[1005]; int dp[1005];// dp[i]表示前原创 2015-09-12 14:00:35 · 266 阅读 · 0 评论 -
HDU 5410 CRB and His Birthday(DP)
题目让求总共m钱最多能买多少物品。 令dp[i][j][0]表示前i种物品,共j钱,不买第i种物品所能买到的最大值。dp[i][j][1]表示前i种物品,共j钱,买第i种物品所能买到的最大值。 那么转移方程为: dp[i][j][0]=max(dp[i-1][j][1],dp[i-1][j][0]) dp[i][j][1]=max(dp[i][j-w[i]][1]+a[i],dp[i][j原创 2015-08-20 20:11:40 · 654 阅读 · 0 评论 -
POJ 4045 Power Station(据说是:树形dp)
题目让从一棵树上找到一个节点,使得其它所有节点到该节点的距离之和最短。若存在不只一个这样的节点,按照节点编号从小到大输出。 两次dfs就好了。 #pragma warning(disable:4996) #include #include #include #include #include using namespace std; typedef long long LL; con原创 2015-09-18 19:56:45 · 343 阅读 · 0 评论 -
HDU 5459 Jesus Is Here(DP)
DP记录答案,更新DP的时候要用到每个cff到其字符串末尾的长度和pos,以及每个cff到其字符串开头的长度和,然后记录一下每个字符串中cff的个数cnt,和字符串长度len,然后乱搞一下就成了。 #pragma warning(disable:4996) #include #include #include #include #include #include using name原创 2015-09-19 20:03:35 · 355 阅读 · 0 评论 -
背包九讲(好好看下还是有好多好东西的)
P01: 01背包问题 题目 有N件物品和一个容量为V的背包。第i件物品的费用是c[i],价值是w[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。 基本思路 这是最基础的背包问题,特点是:每种物品仅有一件,可以选择放或不放。 用子问题定义状态:即f[i][v]表示前i件物品恰放入一个容量为v的背包可以获得的最大价值。则其状态转移方程便转载 2015-09-02 09:08:57 · 301 阅读 · 0 评论 -
hihocoder 1055 刷油漆(树形dp)
题意:有棵节点数为n的树,节点都有对应的分数,要求找到以1为根的包含m个结点的树所得分数最大。 思路:dp[u][j]表示以节点u为根的大小为 j 的树可得到的最大分数,答案就是dp[1][m]。 状态转移方程为:dp[u][j]=max(dp[v1][k1]+dp[v2][k2]+...+dp[vx][kx]),v是u的子节点。 这里就有了泛化物品的概念(不懂的可以去看一下大牛的背包九讲)原创 2015-09-01 23:58:40 · 1157 阅读 · 0 评论 -
HDU 5366 The mook jong(DP)
题意:n个空格中放树桩,树桩之间至少间隔两个空格,问一共有多少种方法 哎。其实我是拒绝说自己比赛的代码的。就是dp嘛 我就是让dp[i][j]表示 i 个空格放 j 个树桩的方法数 然后转移方程就是 dp[i][j]=dp[i-3][j-1]+dp[i-4][j-1]+...+dp[1][j-1]; 意思呢就是第一个空格放个树桩,然后剩下 j-1 个树桩就得放到i-3个空格里(原创 2015-08-09 00:12:06 · 369 阅读 · 0 评论 -
POJ 1384 Piggy-Bank(DP完全背包)
#pragma warning(disable:4996) #include #include #include #define LL long long using namespace std; //很简单的完全背包问题,MLE了 //复习了一下空间的优化 ^_^ ~ ~ LL dp[10005]; int w[505], p[505]; int main(){ int t; sc原创 2015-08-09 10:08:00 · 429 阅读 · 0 评论 -
POJ 2342 Anniversary party(树形DP)
#pragma warning(disable:4996) #include #include #include #include #include #define N 6005 using namespace std; //树形dp:通过“所有”子节点的信息来更新父节点的信息 //g[u]里面放着u的所有儿子 vectorg[N]; //dp[i][0]表示第i个人不参加聚会得到的原创 2015-08-09 12:55:38 · 237 阅读 · 0 评论 -
POJ 1050 To the Max && POJ 2479 Maximum sum(DP最大连续子段和)
先说一下最大连续子段和。 dp可以o(n)地求出最大连续子段和。 若a[i]表示原来的数组,令dp[i]记录以第 i 个数结尾的最大连续子段和。 转移方程是dp[i]=max(dp[i-1]+a[i],a[i]) 程序如下: #pragma warning(disable:4996) #include #include #define N 105 using namespace s原创 2015-08-09 14:47:53 · 304 阅读 · 0 评论 -
HDU 5418 Victor and World(状压dp、最短路)
首先用Folyd求出任意两点间的最短路。 然后令dp[i][S]表示访问情况为S,最后访问i国家的最小花费。 转移方程为dp[i][S|(1 #pragma warning(disable:4996) #include #include #include using namespace std; int mp[17][17]; int dp[17][1 << 16];//dp[i][原创 2015-08-26 15:07:34 · 348 阅读 · 0 评论 -
URAL 1018 Binary Apple Tree(树形dp)
刚开始贪心每次最小的叶子去掉,wa了几次发现思路是错了。正解是简单的树形dp。 #pragma warning(disable:4996) #include #include #include #include using namespace std; vectorg[105]; int num[105][105], cnt[105];//cnt[u]表示结点u的子树中有几条树枝 int原创 2015-08-27 17:13:27 · 375 阅读 · 0 评论 -
hihocoder 1164 随机斐波那契 (期望dp)
其实最简单的暴力O(n^3)是能过的,,这里主要是提一下对于大数据时怎么处理。 对于某个n来说我们要求a_n的期望,考虑一下我们求a_n的时候是随机从a_n前面的n项中抽出两项然后相加得到a_n,那么我们把所有情况分为两类:第一类是所选的两个数中有a_(n-1),第二类是所选的数中没有a_(n-1)。然后分别把两类的期望求出来相加就好了。 对于第一类的期望:它就是从a_0加到a_(n-1)的和原创 2015-08-30 15:54:34 · 955 阅读 · 2 评论 -
hihocoder 1044 状态压缩·一 (状态dp)
题意:n堆垃圾,任意连续的m堆中最多选q堆,求最大垃圾量。 思路:dp[i][S]表示前 i 个人中,第i+1-m个人到第i个人的选取情况为S时,能获得的最大值。 先说第一个比较简单的转移方程:dp[i][S],若S里1的个数大于q,则为0。否则在第i-m堆垃圾的取和不取中选较大值,再加上第i堆的取舍情况。 int cnt = cal(j);//计算出j里面1的个数 if原创 2015-09-01 21:32:01 · 689 阅读 · 0 评论 -
POJ 1159 Palindrome(区间dp)
dp[i][j]表示s[i,...,j]至少添加几个字符变成回文,转移方程为 if (s[i] == s[j]) { dp[i][j] = dp[i + 1][j - 1]; } else { dp[i][j] = min(dp[i + 1][j], dp[i][j - 1]) + 1; } 注意一下i和j的更新顺序就好了。 然后MLE了一下,改为滚动数组就AC了。 #pra原创 2015-09-21 16:18:01 · 305 阅读 · 0 评论