随笔分类 - 动态规划
摘要:http://acm.hdu.edu.cn/showproblem.php?pid=2151简单dp,动态转移方程:dp[N][T]=dp[N-1][T-1]+dp[N-1][T+1],注意判断边界是否存在#include#includeint main(){ int N,P,M,T,i,j; int dp[110][110]; while(scanf("%d%d%d%d",&N,&P,&M,&T)!=EOF) { memset(dp,0,sizeof(dp)); dp[0][P]=1; for(i=1;i0) ...
阅读全文
摘要:http://acm.hdu.edu.cn/showproblem.php?pid=1559这题相对上一题来说多了个限制条件,矩阵大小要是x*y的,这样的话倒更简单,只需计算出连续的x行,连续的y列和最大和即可,纵列和的求解用到了压缩的思想,就是把连续的x行上的同一列的数都相加存储在一个数组列对应的的下标元素里面 1 #include 2 #include 3 int a[1001][1001],n,m,x,y; 4 int maxx(int *b,int k) 5 { 6 int i,max=0,sum[11111]; 7 for(i=0;imax)max=sum[i];17...
阅读全文
摘要:#include#includeint a[110][110],n;int maxx(int *b,int m){ int i,max,now; for(i=0;ib[i]) now+=b[i]; else now=b[i]; if(max0时(即前面的段加上a[j]这一段值会更大,自然把a[j]这一段接上)b[j]=b[j-1]+a[j],否则(由于前面的段为负值,加上a[j],会使值变小,这样的话,我们将前面的段去掉,a[j]即是最大值)b[j]=a[j].故b[j]的动态规划递归式为 b[j]=max(b[j-1]+a[j],a[j]...
阅读全文
摘要:http://acm.hdu.edu.cn/showproblem.php?pid=1712物品分多组,每组中的每件都是冲突的,那么,背包问题变成,在某组中取一个,使得价值达到最大,或者这组一个都不取能使价值达到最大,在01背包基础上加一个循环就可以,在减去体积的时候依次减去每组每一个的体积,这里的体积正好对应纵坐标,所以不必再抽象成c[i]了,价值w[i] 2 int max(int a,int b) 3 { 4 return a>b?a:b; 5 } 6 int main() 7 { 8 int i,k,j,n,m,dp[110],a[110][110]; 9 wh...
阅读全文
摘要:http://acm.hdu.edu.cn/showproblem.php?pid=1114这个题目关键在于两点,一个是完全背包问题,一个是背包是否装满完全背包 就是每个物品都可以无限放入,所以每个dp[j]放的都是目前状态比较后的结果,化为一维数组,为dp[v]=min(dp[v],dp[v-wi]+ci);循环记得是顺序的,这样能保证这一个放入的一定是之前所已知的,因为,是目前的状态题目有N种物品和一个容量为V的背包,每种物品都有无限件可用。第i种物品的费用是c[i],价值是w[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。基本思路这个问题非常类似于01
阅读全文
摘要:首先推一篇文章,写的很清楚http://blog.sina.com.cn/s/blog_8627bf080100t9wv.html理解:在01背包问题当中,内循环用的是逆序,由方程f[v]=max(f[v],f[v-ci]+wi),假定前面的式子都是正确的,那么当我们在推f[j]的时候,进行比较的f[j]和f[j-ci]两者里面保存的必然就是前一状态遗留下来的结果,这样可以一直满足状态转移方程的成立,而至于边界问题是初始化的时候应该解决的void ZeroOnePack(){for(int i=1;i=weight[i];j--)DP[j]=DP[j]>DP[j-weight[i]]+v
阅读全文
摘要:http://acm.hdu.edu.cn/showproblem.php?pid=2069原以为非得用dp。。。后来查了发现暴力就可以了,所以打个表62ms过了,dp完全背包努力中。。。 1 #include 2 int main() 3 { 4 int i,a,b,c,d,e,coin[300]={1},n; 5 for(i=1;i<=250;i++) 6 for(a=0;a<=i;a++) 7 for(b=0;5*b<=i-a;b++) 8 for(c=0;10*c<=i-a-5*b;c++) 9 ...
阅读全文
摘要:http://acm.hdu.edu.cn/showproblem.php?pid=1203简单的01背包问题,与其他的区别在于,要利用“至少得到一份”的对立面的概率去计算,所以,要把每个概率变成1-x,然后求背包最小,记得+wi要改成*wi就可以了,其中还有一个初始化的问题,初始化为无穷大,而这里只需大于等于1就可以了,因为概率最大也就1,这样的比较最小时可以避免没有数值却依然被因为比较出来是最小而存数值进去的错误,这里可以用一维数组,或者滚动数组,两个版本都贴下 1 /*这里用的是滚动数组,时间46ms*/ 2 #include 3 #include 4 double dp[2][1000
阅读全文
摘要:http://acm.hdu.edu.cn/showproblem.php?pid=2571简单dp题目,推算最大的路径和:状态:f[i][j]:从第[i,j]到终点的最大值状态转移:f[i][j]=max{f[i+1][j],f[i][j+1],f[i][j*k](k>1)}初始值:f[n][m]=a[n][m];这是递归的思想,而在dp代码中写出来应该是递推的写法:状态转移:f[i][j]=a[i][j]+max{f[i-1][j],f[i][j-1],f[i][j/k](k>1)}这题关键应该在于初始化,为了保证第一行和第一列保留的都是他们原本的数字,可以在二维矩阵外面再多加
阅读全文
摘要:http://acm.hdu.edu.cn/showproblem.php?pid=2602典型的01背包问题,用动态规划来解即可。用子问题定义状态:即f[i][v]表示前i件物品恰放入一个容量为v的背包可以获得的最大价值。则其状态转移方程便是: f[i][v]=max{f[i-1][v],f[i-1][v-c[i]]+w[i]} 这个方程非常重要,基本上所有跟背包相关的问题的方程都是由它衍生出来的。所以有必要将它详细解释一下:“将前i件物品放入容量为v的背包中”这个子问题,若只考虑第i件物品的策略(放或不放),那么就可以转化为一个只牵扯前i-1件物品的问题。如果不放第i件物品,那么问题就转化
阅读全文
摘要:http://acm.hdu.edu.cn/showproblem.php?pid=1513给一个字符串,求这个字符串最少增加几个字符能变成回文,如Ab3bd可以增加2个字符变为回文:Adb3bdA。通过这样的结论可以和最长公共子串联系起来(未证明):S和S' (注:S'是S的反串)的最长公共子串其实一定是回文的。这样我们就可以借助lcs来解决该题,即用s的长度减去lcs的值即可。#include #include short ans[2][5001];int max(int a,int b){ return a>b?a:b;} int main(){ int i,j,l
阅读全文
摘要:dp过程当中由于递推的方式,经常要的只是最后的一个数据而已,所以前面算出来的数据可放弃,这样可以极大的节省空间,于是有这么一个方法滚动数组举个简单的例子:int d[]=new int[100];d[0]=1;d[1]=1;for(int i=2;i<100;i++)d[i]=d[i-1]+d[i-2];System.out.printf("%d",d[99]);上面这个循环d[i]只需要解集中的前2个解d[i-1]和d[i-2]; 为了节约空间用滚动数组的方法int d[]=new int[3]; d[0]=1;d[1]=1; for(int i=2;i<10
阅读全文
摘要:http://poj.org/problem?id=2081要的就是存储中间数据的思想,避免重复计算Source CodeProblem: 2081 User: 297752873/*Memory: 41280K Time: 32MSLanguage: C Result: AcceptedSource Code*/#include#include int a[500001],hash[10000000];int main(){ int i,k; memset(hash,0,sizeof(hash)); a[0]=0;hash[0...
阅读全文
摘要:http://poj.org/problem?id=1163因为要求的是最大的路径和,那就开个数组存储,然后从倒数第二行开始计算,每条路径上要保留左右子树上的最大数再加上本身的数,然后保留在本身结点位置,可避免重复计算转移方程num(i,j)=max(num(i+1,j),num(i+1,j+1))+num(i,j);#includeint max(int a,int b){ return a>b?a:b;}int main(){ int num[101][101],sum,i,j; scanf("%d",&sum); for(i=0;i=0;i--) ...
阅读全文
摘要:http://acm.hdu.edu.cn/showproblem.php?pid=1331dp打表就是这么个过程了 1 #include 2 #include 3 int main() 4 { 5 int i,j,k,a,b,c; 6 int w[21][21][21]; 7 for(i=0;i20||b>20||c>20)k=w[20][20][20];19 else k=w[a][b][c];20 printf("w(%d, %d, %d) = %d\n",a,b,c,k);21 }22 return 0;23 } Vi...
阅读全文
摘要:http://acm.hdu.edu.cn/showproblem.php?pid=1159这题可用递归解出(1)递归方法求最长公共子序列的长度 1)设有字符串a[0...n],b[0...m],下面就是递推公式。 当数组a和b对应位置字符相同时,则直接求解下一个位置;当不同时取两种情况中的较大数值。 #include//会超时 #includechar a[100000],b[100000];int lena,lenb;int LCS(int i,int j){ if(i>=lena || j>=lenb) return 0; if(a[i...
阅读全文
摘要:DP对于动态规划,每个刚接触的人都需要一段时间来理解,特别是第一次接触的时候总是想不通为什么这种方法可行,这篇文章就是为了帮助大家理解动态规划,并通过讲解基本的01背包问题来引导读者如何去思考动态规划。本文力求通俗易懂,无异性,不让读者感到迷惑,引导读者去思考,所以如果你在阅读中发现有不通顺的地方,让你产生错误理解的地方,让你难得读懂的地方,请跟贴指出,谢谢!----第一节----初识动态规划--------经典的01背包问题是这样的:有一个包和n个物品,包的容量为m,每个物品都有各自的体积和价值,问当从这n个物品中选择多个物品放在包里而物品体积总数不超过包的容量m时,能够得到的最大价值是多少
阅读全文
摘要:http://poj.org/problem?id=2533简单的dp运用于求最长有序子序列,这里是递增我们假设原数列定义为数组a[],然后定义一个数组b[i],表示以a[i]结尾的最长公共子序列的长度,只要求出所有的b[i]数组也就可以确定最长的公共子序列, 那么我们根据已经求出的b[0]--b[i-1],来求b[i]呢,,也就如何求出以a[i]结尾的最大公共子序列的长度呢, 此时在a[0]-a[i-1]范围内,已经求出多个长度的公共子序列,且最大长度的一个序列的长度为s,这个序列的最后一个元素为t,那么 1.如果a[i]t,这时候就会比较的麻烦了,因为a[i]不可能成为长度为s的最长公共子
阅读全文
摘要:http://acm.hdu.edu.cn/showproblem.php?pid=1003初识dp,大问题是求出总序列的最大和,而每个数都有加到前面作为前面已经加好的和的增量和自己独立成为一个“最大和”的选择,在这两个选择中的最大和就是局部的最大和,而保存好第一个最大和,将整个序列的所有局部最大和都求解出来,就能得到全列的最大和#includeint main(){ int i,ca=1,t,s,e,n,x,now,before,max; scanf("%d",&t); while(t--) { scanf("%d",&n); for(
阅读全文

浙公网安备 33010602011771号