
动态规划DP
stdwal
天演在化,功成在学。知海无涯,见花问道。
展开
-
POJ2385-Apple Catching
简单dp。dp[i][j]表示在第i分钟,走了第j步后所得的苹果数。因此dp[i][j]取决于dp[i-1][j-1]和dp[i-1][j],以及所在的树上是否掉落苹果。#include #include using namespace std;const int MAXT = 1000;const int MAXW = 30;int dp[MAXT+2][MAXW+2原创 2016-04-26 19:04:14 · 279 阅读 · 0 评论 -
POJ1276-Cash Machine
一个多重背包问题,我们可以将多重背包转换为01背包问题,然后暴力解决。 由于cash的值很大,因此直接从cash开始dp会超时,因此我们可以手动设置一个已知的最大cash,记为val,dp[i]表示i这个数是否已经被作为val,这样每次从val开始dp,能够节省一部分的时间。 剩下的就是01背包了。//POJ1276#include <cstdio>#include <cstring>#i原创 2016-09-01 21:39:11 · 258 阅读 · 0 评论 -
POJ3267-The Cow Lexicon
dp[i]表示从i到message末尾最少需要删去的字符数。 枚举每个单词进行匹配,不断更新最小删去数。#include <cstdio>#include <cstring>#include <algorithm>using namespace std;char mesg[400];char dict[650][50];int dp[400];int main(int argc, char原创 2016-10-21 20:27:12 · 259 阅读 · 0 评论 -
HDU5904-LCIS
小小的瞎dp一下。 不过题目要求数据范围1e6,但是开1e6的数组会爆栈导致TLE,开1e5的数组就能过,数据太水而且题目没有出好,差评!#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int maxn = 100000+5;int a[maxn];int b[maxn];int原创 2016-09-26 21:10:18 · 423 阅读 · 0 评论 -
POJ1837-Balance
乍一看是一道暴搜题,但是暴搜显然会超时。 正确做法是01背包,引入平衡度的概念,用dp的方式统计求解。#include <cstdio>int h[25];int w[25];//dp[i][j]表示挂满前i个钩码时,平衡度为j的挂法的个数int dp[25][15000+5];int main() { int c, g; scanf("%d%d", &c, &g);原创 2016-10-18 16:55:51 · 318 阅读 · 0 评论 -
POJ1836-Alignment
枚举并分别LIS即可。#include <cstdio>#include <algorithm>using namespace std;const int maxn = 1000 + 5;const double INF = 3.0;double line[maxn];double dp1[maxn];double dp2[maxn];int main() { int n; s原创 2016-10-19 18:10:51 · 324 阅读 · 0 评论 -
POJ1050&HDU1081-To the Max
从一个矩阵中寻找和最大的子矩阵,简单的枚举各种情况即可。 数组a表示原矩阵,b表示a中的某几行之和组成的新序列,这样就转换为求新序列的最大连续子序列的和问题了。#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int maxn = 100 + 5;int a[maxn][maxn];原创 2016-08-17 11:03:45 · 271 阅读 · 0 评论 -
Ural1073-Square Country
给定一个数n,求这个数最少由几个完全平方数相加得到。 状态转移方程:dp[i] = ∑dp[i-j*j]+1.#include <cstdio>#include <algorithm>const int maxn = 60000 + 5;const int inf = maxn;int dp[maxn];int main(int argc, char const *argv[]) {原创 2016-12-05 16:37:39 · 500 阅读 · 0 评论 -
Ural1353-Milliard Vasya's Function
给定一个数s,求从1到1e9的数中各位相加等于s的个数。#include <cstdio>// dp[i][j]表示长度为i,各位之和为j的个数int dp[15][90];int main(int argc, char const *argv[]) { for (int i = 1; i < 10; i++) { dp[1][i] = 1; } for (原创 2016-11-26 10:57:44 · 396 阅读 · 0 评论 -
POJ1141-Brackets Sequence
用dp[i][j]记录下从i到j所缺少的括号数量,那么dp[i][i] = 1,dp[i][j] = dp[i][k] + dp[k+1][j],另外如果第i个字符和第j个字符匹配,则dp[i][j]应先被置为dp[i+1][j-1]。 由于要输出最终的字符串,所以使用pos[i][j]记录下缺省的位置,输出也是一个难点,要写一个函数递归的输出配对后的合法字符串,代码仅供参考。//POJ1141原创 2016-09-01 21:00:13 · 410 阅读 · 0 评论 -
POJ1661-Help Jimmy
很棒的题,一开始用搜索做一直不对,后来才发现是DP。 将一开始的位置和地面都看作是一个平台。 先将每个平台按照高度从小到大排序。 dp[i][[0]和dp[i][1]分别表示从第i个平台从左端和从右端到地面的最小时间,那么dp[i]就取决于高度低于i平台的可到达的第一块平台k,dp[i][0] = 高度差 + min(dp[k][0]+i左端到k左端的距离, dp[k][1] + i左端到k原创 2016-09-01 20:53:51 · 306 阅读 · 0 评论 -
01背包问题
01背包问题有n个重量和价值分别为wi,vi的物品。从这些物品中挑选出总重量不超过W的物品,求所有挑选方案中价值总和的最大值。1 1001 1001 10000int n, W;int w[MAX_n], v[MAX_n];//从第i个物品开始挑选总重小于j的部分int rec(int i, int j){ int res; if (i原创 2016-04-06 15:18:37 · 395 阅读 · 0 评论 -
POJ3176-Cow Bowling
这么多天对DP还是研究的不够透彻,DP入门第一题。初始条件为dp[0][0]=tip的值,其余dp[i][j]取决于dp[i-1][j]和dp[i-1][j-1]和本身dp[i][j]的值。#include #include #include using namespace std;const int MAXN = 350;int bowl[MAXN+5][MAXN+5];原创 2016-04-17 17:03:49 · 306 阅读 · 0 评论 -
POJ2229-Sumsets
一开始想的很复杂还列了一个2的幂次表,最后还是被困住了。在Discuss里看到了一个巨巨的思路,不仅高效而且简明:dp[i]为数字i的最多组合数。将i分奇偶考虑:如果i是奇数,i的任意一个组合都包含1,即dp[i-1]的每一种组合后+1,因此dp[i] = dp[i-1]。如果i是偶数,i的组合数为i-1的组合数(每种组合后+1)以及i / 2的组合数(每种组合*2)之和。原创 2016-04-18 21:15:52 · 320 阅读 · 0 评论 -
POJ3616-Milking Time
首先将Bessie休息的时间纳入挤奶的时间内,按开始时间从小到大排序。然后用每个挤奶时间内的牛奶量初始化dp数组,dp[i]表示从开始到第i个时间内收益的最大值。显然dp[i] = 从0 - i 时间段内的最大收益+当前第i个时间段内收益。#include #include using namespace std;const int MAXM = 1000;struct原创 2016-05-04 13:51:44 · 301 阅读 · 0 评论 -
最长上升子序列长度及其个数
求最长上升子序列长度的两种方法:int a[MAXN];int dp[MAXN];int lis = 0;for (int i = 0; i < n; i++) { dp[i] = 1; for (int j = 0; j < i; j++) { if (a[j] < a[i]) dp[i] = max(dp[i], dp[j]原创 2016-05-04 13:00:07 · 1799 阅读 · 0 评论 -
POJ3280-Cheapest Palindrome
动态规划。dp[i][j]表示把从id[i]到id[j]改成回文串的最小代价。因此每次dp[i][j]都将从规模更小的dp[i+1][j]和dp[i][j-1]中选择最优解。通过每次迭代,dp[i+1][j]是回文串,dp[i][j-1]也是回文串。设从id[i+1]到id[j]的回文串为xxyy则从id[i]到id[j]的字符串为axxyy,这时可以将该字符串改成axxyya原创 2016-05-22 00:52:09 · 323 阅读 · 0 评论 -
POJ2686-Traveling by Stagecoach
状态压缩dp,将n张马票看作n种状态进行状态压缩。 s代表到达剩下的车票集合,v代表现在所在的城市。 d[s][v]表示所需的最小费用。 这样一来,dp[s{i}][u] = min(dp[s{i}[u], dp[s][v] + d[v][u] / t[i])#include <cstdio>#include <cstring>#include <algorithm>using names原创 2016-08-28 20:40:13 · 470 阅读 · 0 评论 -
POJ1821-Fence
这是一道经典的单调队列优化DP. 首先不难看出要用动态规划求解,dp[i][j]表示第i个工人粉刷第j块木板时的最大收益,由此 dp[i][j] = max( dp[i-1][j] 第i个工人不刷木板 dp[i-1][k] + (j - k) * p 第i个工人从第k+1块木板开始一直刷到第j块 ) 由于每个工人粉刷的木板必须包含s,因此dp[i][…原创 2016-09-07 22:31:51 · 390 阅读 · 0 评论 -
Ural1523-K-inversions
给定n个数字和一个k,求长度为k的下降子序列的个数。 dp[i][j]表示以a[i]为结尾,长度为j的下降子序列的个数。 因此: dp[i][j] = Sigma(dp[k][j-1]),其中k属于[1, i),且a[k] > a[i]. 维护一个树状数组以便于快速求出所有满足条件的dp[k][j-1]的总和。 先初始化dp数组,将dp[i][1]置为1,然后,更新dp[i][j],再在树原创 2016-11-21 11:39:55 · 457 阅读 · 0 评论