动态规划的问题总结
2017-06-30 00:01
99 查看
1、dp[个数][weight] (例子:poj 1837 Balance)
dp[i][w]=relate to (dp[i-1][w-c[j]])
这道题中dp存储的不是weight,而是方法个数
2、dp[所有可能的值] (例子:poj 1276 Cash Machine)
if(dp[i]) dp[i+w[t]*k]=1; 有时候Bool类型更好
3、3276 The Cow Lexicon
dp[i]=dp[j]+w[i,j] / dp[i]=dp[j]+w[j,i] 一个是倒着,一个是顺着
dp[i]=dp[i+1]+1 //把这个给删除了
dp[i]=dp[j]+j-i-len //i~j的串删除一些字符后能和Len匹配的
4 、POJ 1836 Alignment
难一些的最大上升子序列
![](https://img-blog.csdn.net/20170702105929319?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvemlxaTkyMTY=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
顺着求一次最大上升子序列dpl,倒着求一次最大上升子序列dpr,然后求dpl[i]+dp=i”>j的最大值
(别人的代码,参考博客:http://blog.csdn.net/lin375691011/article/details/11137083)
5 、POJ 1260 Pearls
题目有点难懂,懂了之后就是dp[i]=dp[j]+w[i,j]的最小值,遍历j
dp 数组的memset很重要!!!!!!!
6 、POJ 1080 Human Gene Functions
编辑距离的变式
7、poj 1159 Palindrome
这道题我以为是一个字符串和他的反向字符串求编辑距离的问题,但是仔细想想就不对,ab字符串和ba字符串的编辑距离就是2,而实际上需要添加的字符个数其实只有1个,所以仔细想想应该也可以用编辑距离的模板去套用,不过目的是求一个字符串和他的反向字符串得公共最大字符串长度n,然后用字符串的长度L减去n就是最后的结果,比如说Ab3bd与db3bA的公共子串是b3b,为3,5-3=2就为最后的结果。
Accepted 184K 891MS
//这也告诉了我一种新的关于求公共子序列的方法哈哈
动态规划—->最优二分检索树
http://blog.csdn.net/ncepuzhuang/article/details/8924369
代码:
http://blog.csdn.net/sunkun2013/article/details/49908585
dp[i][w]=relate to (dp[i-1][w-c[j]])
这道题中dp存储的不是weight,而是方法个数
#include<iostream> #include<cstdio> #include<cstring> #include<vector> #include<queue> #include<algorithm> #define MAXNUM 15000 using namespace std; int dp[25][MAXNUM], C, G, good[25], w[25]; int main() { //freopen("1.txt", "r", stdin); int i, j, k, a, b, c, sum, cases; scanf("%d%d", &C, &G); for (i = 1; i <= C; i++) scanf("%d", &good[i]); for (i = 1; i <= G; i++) scanf("%d", &w[i]); dp[0][7500] = 1; for (i = 1; i <= G; i++) { for (j = 0; j <= MAXNUM; j++) { if (dp[i - 1][j]) { for (k = 1; k <= C; k++) dp[i][j + good[k] * w[i]] += dp[i - 1][j]; } } } printf("%d\n", dp[G][7500]); return 0; }
2、dp[所有可能的值] (例子:poj 1276 Cash Machine)
if(dp[i]) dp[i+w[t]*k]=1; 有时候Bool类型更好
#include<iostream> #include<cstdio> #include<cstring> #include<vector> #include<queue> #include<algorithm> #define CASH 100005 using namespace std; bool dp[CASH]; int N, cash, n[20], D[20]; int main() { //freopen("1.txt", "r", stdin); int i, j, k, a, b, c, res; while (scanf("%d%d", &cash, &N) != EOF) { memset(dp, 0, sizeof(dp)); memset(n, 0, sizeof(n)); memset(D, 0, sizeof(D)); for (i = 0; i < N; i++) scanf("%d%d", &n[i], &D[i]); if (!N || !cash) { printf("0\n"); continue; } res = 0; dp[0] = 1; for (i = 0; i < N; i++) { for (j = res; j >= 0; j--) { if (dp[j]) for (k = 1; k <= n[i]; k++) { a = j + k*D[i]; if (a <= cash) { dp[a] = 1; res = max(res, a); } } } } printf("%d\n", res); } return 0; }
3、3276 The Cow Lexicon
dp[i]=dp[j]+w[i,j] / dp[i]=dp[j]+w[j,i] 一个是倒着,一个是顺着
dp[i]=dp[i+1]+1 //把这个给删除了
dp[i]=dp[j]+j-i-len //i~j的串删除一些字符后能和Len匹配的
#include<iostream> #include<vector> #include<cstdio> #include<cstring> #include<algorithm> #include<queue> #include<string> #include<math.h> using namespace std; int dp[305], W, L; char ss[305]; string strs[610]; int main() { //freopen("1.txt", "r", stdin); int i, j, k, t, a, b, len, flag; while (scanf("%d%d", &W, &L) != EOF) { memset(dp, 0, sizeof(dp)); //memset(ss, 0, sizeof(ss)); scanf("%s", ss); for (i = 0; i < W; i++) cin >> strs[i]; for (i = L - 1; i >= 0; i--) { dp[i] = dp[i + 1] + 1; for (j = 0; j < W; j++) { len = strs[j].length(); if (len <= L - i&&ss[i] == strs[j][0]) { int pm = i; int pi = 0; while (pi < len&&pm < L) { if (ss[pm++] == strs[j][pi]) pi++; if (pi == len) { dp[i] = min(dp[i], dp[pm] + pm - i - len); break; } } } } } printf("%d\n", dp[0]); } return 0; }
4 、POJ 1836 Alignment
难一些的最大上升子序列
顺着求一次最大上升子序列dpl,倒着求一次最大上升子序列dpr,然后求dpl[i]+dp=i”>j的最大值
(别人的代码,参考博客:http://blog.csdn.net/lin375691011/article/details/11137083)
#include <stdio.h> #include <string.h> const int MAX=1005; int main() { int n,dpl[MAX],dpr[MAX]; double hi[MAX]; while(scanf("%d",&n)!=EOF) { int i,j; for(i=0; i<n; i++) { scanf("%lf",&hi[i]); } memset(dpr,0,sizeof(dpr)); memset(dpl,0,sizeof(dpl)); dpl[0]=1; for(i=1;i<n;i++) { dpl[i]=1; for(j=i-1;j>=0;j--) { if(hi[j]<hi[i]&&dpl[j]+1>dpl[i]) { dpl[i]=dpl[j]+1; } } } dpr[n-1]=1; for(i=n-2;i>=0;i--) { dpr[i]=1; for(j=i+1;j<=n-1;j++) { if(hi[j]<hi[i]&&dpr[j]+1>dpr[i]) { dpr[i]=dpr[j]+1; } } } int ans=dpl[n-1]; for(i=0;i<n-1;i++) { for(j=i+1;j<n;j++) { if(dpl[i]+dpr[j]>ans) { ans=dpl[i]+dpr[j]; } } } printf("%d\n",n-ans); } return 0; }
5 、POJ 1260 Pearls
题目有点难懂,懂了之后就是dp[i]=dp[j]+w[i,j]的最小值,遍历j
#include<iostream> #include<vector> #include<cstdio> #include<cstring> #include<algorithm> #include<queue> #include<string> #include<math.h> using namespace std; int price[110], num[110], dp[110], sum[110]; int main() { //freopen("1.txt", "r", stdin); int i, j, k, t, tmp, cases; scanf("%d", &cases); while (cases > 0) { memset(price, 0, sizeof(price)); memset(num, 0, sizeof(num)); memset(sum, 0, sizeof(sum)); memset(dp, 0, sizeof(dp)); scanf("%d", &k); for (i = 1; i <= k; i++) { scanf("%d%d", &num[i], &price[i]); sum[i] = sum[i - 1] + num[i]; } dp[1] = (num[1] + 10) * price[1]; for (i = 2; i <= k; i++) { dp[i] = (num[i] + 10) * price[i] + dp[i - 1]; for (j = 0; j < i - 1; j++) { tmp = (sum[i] - sum[j] + 10)*price[i] + dp[j]; dp[i] = min(dp[i], tmp); } } cases--; printf("%d\n", dp[k]); } return 0; }
dp 数组的memset很重要!!!!!!!
6 、POJ 1080 Human Gene Functions
编辑距离的变式
#include<iostream> #include<vector> #include<cstdio> #include<cstring> #include<algorithm> #include<queue> #include<string> #include<math.h> #define MAXNUM 250 using namespace std; int dp[MAXNUM][MAXNUM]; char str1[MAXNUM], str2[MAXNUM]; int rep1[MAXNUM], rep2[MAXNUM]; int insert[4] = { -3, -4, -2, -1 }; int contrast[4][4] = { { 5, -1, -2, -1 }, { -1, 5, -3, -2 }, { -2, -3, 5, -2 }, { -1, -2, -2, 5 } }; int main() { //freopen("1.txt", "r", stdin); int i, j, k, t, tmp1, tmp2, cases, len1, len2; scanf("%d", &cases); while (cases > 0) { memset(rep1, 0, sizeof(rep1)); memset(rep2, 0, sizeof(rep2)); memset(dp, 0, sizeof(dp)); scanf("%d%s", &len1, str1 + 1); for (i = 1; i <= len1; i++) { if (str1[i] == 'A') rep1[i] = 0; else if (str1[i] == 'C') rep1[i] = 1; else if (str1[i] == 'G') rep1[i] = 2; else if (str1[i] == 'T') rep1[i] = 3; } scanf("%d%s", &len2, str2 + 1); for (i = 1; i <= len2; i++) { if (str2[i] == 'A') rep2[i] = 0; else if (str2[i] == 'C') rep2[i] = 1; else if (str2[i] == 'G') rep2[i] = 2; else if (str2[i] == 'T') rep2[i] = 3; } dp[0][0] = 0; for (i = 1; i <= len1; i++) { dp[i][0] = insert[rep1[i]] + dp[i - 1][0]; } for (i = 1; i <= len2; i++) { dp[0][i] = insert[rep2[i]] + dp[0][i - 1]; } for (i = 1; i <= len1; i++) for (j = 1; j <= len2; j++) { tmp1 = dp[i][j - 1] + insert[rep2[j]]; tmp2 = dp[i - 1][j] + insert[rep1[i]]; tmp1 = max(tmp1, tmp2); tmp2 = dp[i - 1][j - 1] + contrast[rep1[i]][rep2[j]]; dp[i][j] = max(tmp1, tmp2);; } printf("%d\n", dp[len1][len2]); cases--; } return 0; }
7、poj 1159 Palindrome
这道题我以为是一个字符串和他的反向字符串求编辑距离的问题,但是仔细想想就不对,ab字符串和ba字符串的编辑距离就是2,而实际上需要添加的字符个数其实只有1个,所以仔细想想应该也可以用编辑距离的模板去套用,不过目的是求一个字符串和他的反向字符串得公共最大字符串长度n,然后用字符串的长度L减去n就是最后的结果,比如说Ab3bd与db3bA的公共子串是b3b,为3,5-3=2就为最后的结果。
Accepted 184K 891MS
//这也告诉了我一种新的关于求公共子序列的方法哈哈
#include<iostream> #include<vector> #include<cstdio> #include<cstring> #include<algorithm> #include<queue> #include<string> #include<math.h> #define MAXNUM 5050 using namespace std; int dp[2][MAXNUM], N; char str1[MAXNUM], str2[MAXNUM]; int main() { //freopen("1.txt", "r", stdin); int i, j, k, t, tmp1, tmp2, cases, len; while (scanf("%d", &N) != EOF) { memset(dp, 0, sizeof(dp)); memset(str1, 0, sizeof(str1)); memset(str2, 0, sizeof(str2)); scanf("%s", str1 + 1); len = N; for (i = 1; i <= len; i++) str2[i] = str1[len + 1 - i]; for (i = 1; i <= len; i++) { dp[1][0] = 0; for (j = 1; j <= len; j++) { if (str1[i] == str2[j]) dp[1][j] = dp[0][j - 1] + 1; else { tmp1 = max(dp[0][j], dp[1][j - 1]); dp[1][j] = max(tmp1, dp[0][j - 1]); } } for (j = 0; j <= len; j++) dp[0][j] = dp[1][j]; } printf("%d\n", N - dp[1][len]); } return 0; }
动态规划—->最优二分检索树
http://blog.csdn.net/ncepuzhuang/article/details/8924369
代码:
http://blog.csdn.net/sunkun2013/article/details/49908585
相关文章推荐
- 动态规划 4、基础背包问题总结(多重背包与多重背包的转化)
- 动态规划(一)最长公共子序列问题 LCS 总结
- 【笔记】【算法学习】【动态规划】背包问题总结(1)
- 动态规划总结(背包问题的深入理解)
- LeetCode总结,动态规划问题小结
- 动态规划、贪心、回溯、分支限界法解0-1背包问题总结
- 杭电acm step 动态规划专题总结(1)简单的动态规划问题
- 动态规划之背包问题-总结和拓展(二)
- 动态规划经典问题总结
- 动态规划 4、基础背包问题总结(从01开始)
- 动态规划的简要总结和四个经典问题的c++实现
- 动态规划之背包问题-总结和拓展(二)
- 动态规划预测游戏输赢的问题总结
- 关于ASP.NET在IIS一些问题的经验总结(zz)
- ASP.NET与IIS配置问题总结!
- 解决问题总结
- 关于ASPNET在IIS一些问题的经验总结
- Eclipse+Jboss使用小问题总结
- 易混问题总结---(by value VS by reference)
- [导入]关于ASPNET在IIS一些问题的经验总结