动态规划的问题总结
来源:互联网 发布:影楼美工 编辑:程序博客网 时间:2024/04/29 09:26
1、dp[个数][weight] (例子:poj 1837 Balance)
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 15000using 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 100005using 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 250using 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 5050using 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
- 动态规划的问题总结
- 动态规划问题总结
- 动态规划问题总结
- 动态规划问题总结
- 动态规划问题总结
- 动态规划问题 (dynamic programming)的总结
- LintCode 关于动态规划问题的总结
- 动态规划-背包问题总结
- 动态规划问题个人总结
- 常见动态规划问题总结
- 动态规划经典问题总结
- 经典动态规划问题总结
- 动态规划----贪心的动态规划问题
- 动态规划总结(背包问题的深入理解)
- 动态规划预测游戏输赢的问题总结
- 关于动态规划的总结
- 动态规划的总结分析
- 动态规划的一些总结
- html中文编码
- C#中如何使用正则表达式
- Idea创建maven的scala项目,没有scala class选项
- 三、工单流程JBPM-------JBPM和SSH2结合使用jar包详解
- HTTP协议入门
- 动态规划的问题总结
- 微信发送模版消息报47001错误
- 【基本数据类型对象包装类】
- jquery调用webservice
- JavaScript的本地对象
- 五、工单流程JBPM------资源库和运行时表结构(数据库表解释 )
- Java常量池简单认识
- Laravel基础-blade模板引擎之变量操作
- cookie 和 session