随笔分类 - ACM-动态规划
摘要:这题是求数字三角形由顶到底边最大数字和对应的路径,在准备夏令营的时候红皮教材上面有,当时没有学动态规划算法,不是很理解,经过这一阵对算法的学习和POJ训练,总算在10分钟内独立思考AC,其实挺简单,满足最优子结构和无后效性,是经典的动态规划问题。一般的思考方法是,由特殊情况比如题目给的示例数据入手,分析如何计算辅助数组dp的值,dp[i][j]记录以r[i][j]为顶点向下走到底边可以得到的最大和,dp数组底边的值就是数字三角形底边数字,然后从底向上计算,dp数组的计算方程(即动态规划状态方程)为dp[i][j] = max(r[i][j] + dp[i+1][j] , r[i][j] + d
阅读全文
摘要:今天看了看背包九讲,自己写了下0-1背包和完全背包王晓东《计算机算法分析与设计》上面给出的C++实现比较繁琐,相比而言这个版本更加简明给出了测试数据0-1背包问题C++实现/*任务:计算0-1背包问题的最大价值
Sample Input
10 4
2 1
3 3
4 5
7 9
Sample Output
12
0 1 0 1
*/
#include<stdio.h>
#include<string.h>
int c[20][1000];//c[k][y]为只允许装前k种物品,背包总重量不超过y的最大价值
int inumber[21][1000];//inumber[
阅读全文
摘要:背包问题 它是在1978年由Merkel和Hellman提出的。它的主要思路是假定某人拥有大量物品,重量各不同。此人通过秘密地选择一部分物品并将它们放 到背包中来加密消息。背包中的物品中重量是公开的,所有可能的物品也是公开的,但背包中的物品是保密的。附加一定的限制条件,给出重量,而要列出可能的物 品,在计算上是不可实现的。背包问题是熟知的不可计算问题,背包体制以其加密,解密速度快而其人注目。但是,大多数一次背包体制均被破译了,因此现在很少有人使用它。DD牛的背包九讲P01: 01背包问题 题目 有N件物品和一个容量为V的背包。第i件物品的费用是c,价值是w。求解将哪些物品装入背包可使这些物..
阅读全文
摘要:这题和编程之美上面的“地板覆盖”问题有点像,不同的是,编程之美上面只需要判定能否覆盖,这题需要求出总方案数目结题报告转自http://duanple.blog.163.com/blog/static/709717672008930104124684/题意:给你一个h*w的矩形,用一个1*2的小矩形去填充,问有多少种填充方法,不考虑对称性。关键点提示:1.DFS部分实际上是在枚举第i行的放置方法,由此便可以确定出该行及上一行的状态。对于第i行,状态(参数next_stat)的定义是指,前i-1行完全放满,第i行的所有位置是否放置(0,1表示)组成的二进制序列,转化为十进制数后所代表的状态。放置方
阅读全文
摘要:本题为多重背包问题,即每种零钱的个数是有限个,求不超过目标钱数的可以组合出的最大钱数采用DP的思想,先对目标钱数以内的所有面额做逆向遍历,初始dp[0] = true,即0元可凑出在此基础上如果当前的stat可以凑出,那么继续组合出更大的钱数,记下当前有限个零钱和前面的零钱一起可以凑出的不超过目标钱数的所有合法的值。最后从money逆向打印记下的最大的值即可Source CodeProblem: 1276User: yangliuACMerMemory: 640KTime: 516MSLanguage: C++Result: Accepted#include <iostream>u
阅读全文
摘要:在王晓东算法书上有讲解,是最大子序列和问题的拓广#include <iostream>using namespace std;int rec[102][102];int b[100];int main(){ int n,k,s,sum,max; int i,j; cin>>n; for (i = 0;i < n;i++) for (j = 0;j < n;j++) { cin>> rec[i][j]; } s = 0; for (i = 0;i < n;i++) { for (k = 0;k < n;k++) b[k] = 0; fo
阅读全文
摘要:在刘汝佳黑书上有详细的解析,自己明天这两种算法自己实现一下,作为对动态规划的深入理解学习先转一个题解http://blog.163.com/leyni@126/blog/static/16223010220103155534476/?fromdm&fromSearch&isFromSearchEngine=yes问题:括号匹配问题。给出一个由括号组成字符串,加最少的括号使之匹配。思路:设f[i][j]为从i到j这段字串达到匹配所需最少括号数。初始状态:f[i][i] = 1;状态转移:f[i][j] = min{f[i + 1][j - 1 | s[i]与s[j]匹配],f[i
阅读全文
摘要:这是一道比较简单的DP,通过分析可以设最后拿走的牌为i,则所求的最优解就是i左边和右边子列的最小连乘积再加上x[a]*x[i]*x[b],因为i将原来的序列划分为两个子列,这两个子列符合“最优子结构”和“重叠子问题”的dp特点,他们的最优解互相之间没有影响,只会影响全局问题的最优解,在POJ discuss中的解析比较经典,摘录如下,以后做题可以常常看看discuss,就当学习,但是还是要独立思考为主对于整个牌的序列,最左端和最右端的牌是不能被取走的,除这两张以外的所有牌> ,必然有一张最后取走。取走这最后一张牌有一个仅与它本身以及最左端和最右端的> 牌的值有关的得分,这个分值与其
阅读全文
摘要:题意描述: john现有h个小时的空闲时间,他打算去钓鱼。john钓鱼的地方共有n个湖,所有的湖沿着一条单向路顺序排列(john每在一个湖钓完鱼后,他只能走到下一个湖继续钓), john必须从1号湖开始钓起,但是他可以在任何一个湖结束他此次钓鱼的行程。john在每个湖中每5分钟钓的鱼数(此题中以5分钟作为单位时间),随时间的增长而线性递减。而每个湖中头5分钟可以钓到的鱼数以及每个湖中相邻5分钟钓鱼数的减少量,input中均会给出。并且John从任意一个湖走到它下一个湖的时间input中也都给出。问题: 求一种方案,使得john在有限的h小时中可以钓到尽可能多的鱼。 output中需包...
阅读全文
摘要:数塔问题的变形,每一层代表一秒,但要注意下一秒到这一秒,除了左右外还有自己本身这个位置,不能忽略即dp[i][j]=max{dp[i+1][j-1],dp[i+1][j],dp[i+1][j+1]}#include <iostream>using namespace std;int dp[100002][12];int max(int a,int b){ return a>b?a:b;}int main(){ int n,i,j,maxt; int x,t; while(scanf("%d",&n),n!=0) { maxt = 0; memset
阅读全文
摘要:HDU 1159 最长公共子序列问题详见杭电刘春英老师PPT//DP算法://用f[i][j] 表示字符串a的第i个字母与字符串b的第j个字母比较,得到两串相比时第i和第j个字母之前相同字母的个数// 如果a[i-1]==b[j-1], f(i,j)= f(i-1,j-1)+1;否则,f(i,j)=max(f(i,j-1),f(i-1,j));#include<iostream>#include<string>using namespace std;int main(){ int f[500][500]; char a[500],b[500]; int i,j,lena
阅读全文
摘要:第一道背包问题,0-1背包,参考网上一位大牛写的做的。状态方程:dp[i][w] = max{dp[i-1][w], dp[i-1][w-obj[i].wei] + obj[i].val]},但这样会超内存,需要一个空间复杂度的优化将dp改为一维,这招看来以后得常用,具体见转载的《背包九讲》。 明天好好读读《背包九讲》,在多做几道dp变形题,练习在于精不在多。#include <iostream>using namespace std;const int mMax = 3500;//待选物品个数const int nMax = 14000;//最大容量struct{ int wei
阅读全文
摘要:这题想了很久,是经典的动态规划问题,感觉有点难度,在网上看了很多讨论。 看了动态规划还要好好加强。#include <iostream>using namespace std;int main(){ long i,j,k,l,n,m,t1,maxf,count; long p[210],d[210],f[210],s[210]; long can[30]; long res[30][1000],from[30][1000]; count=0; cin>>n>>m; while(n!=0 || m!=0) { count++...
阅读全文
摘要:在输入的同时,进行一次DP,计算出从左到右的最大值,并把它保存在数组dp的对应的下标元素中,这样之后,对于下标为i的元素,它其中保存的便是前面所有元素可能的最大连续和。再从右到左进行一次DP,计算从右到左的最大连续和。假设此时已经算到下标为i的元素,那么将sum+dp[i-1]与ans进 行比较,将ans取较大者。最后当i到2的时候ans中的值即为所求的最大值。#include <iostream>using namespace std;int dp[100001],num[100001];const int MINNUM = -99999999;int main(){ int c
阅读全文
浙公网安备 33010602011771号