动态规划,背包问题的解题思路

01背包问题:

        有n种物品,每种只有一个。第i种物品的体积为Vi,重量为Wi。选一些物品装到一个容量为C的背包,使得背包内物品总体积不超过C的前提下重量尽可能的大。

1<=n<=100,1<=Vi<=C<=10000,1<=Wi<=10^6。


      解题思路:定义一个二维数组,第一维i为总共的物品数量,第二维j为剩余体积数量。每一维都尝试把所有的装进去,然后多余的空间装上一维的能装下的体积。直到最后一维,d[ i ][ j ]最大的那个即为Wi最大的那个。(必须倒着装)。

具体实现代码如下:

<span style="font-size:14px;">for(int i=n;i>=1;i--)//因为后面会出现i>n的情况,所以定义时数组要开大一位,超过n初始化为0,且只能逆序,正序会有d[-1]出现
    for(int j=0;j<=c;j++)
    {
            d[i][j]=(i==n?0:d[i+1][j])//给它赋值前一位的数值,因为这一步的存在,所以可以用一维数组而不是二维
            if(j>=V[i])  d[i][[j]=max(d[i][j],d[i][j-V[i]]+Wi)//对比一下当使用空间相等时,用剩V[i]空间的值加Wi之后是
//否比当前大,大的话就替换。
    }

</span>

一位数组版本:


<span style="font-size:14px;">memset(f,0,sizeof(f));
for(int i=1;i<=n;i++)
{
    cin>>V>>W;
    for(int j=C;j>=0;j--)
    {
         if(j>=V)  f[j]= max(f[j],f[j-V]+W)
    }
}//功能完全一样,思路完全一样
只是两种方法输出的方式会有差异。
</span>



A - 数塔


在讲述DP算法的时候,一个经典的例子就是数塔问题,它是这样描述的:

有如下所示的数塔,要求从顶层走到底层,若每一步只能走到相邻的结点,则经过的结点的数字之和最大是多少?

已经告诉你了,这是个DP的题目,你能AC吗?
 

Input

输入数据首先包括一个整数C,表示测试实例的个数,每个测试实例的第一行是一个整数N(1 <= N <= 100),表示数塔的高度,接下来用N行数字表示数塔,其中第i行有个i个整数,且所有的整数均在区间[0,99]内。
 

Output

对于每个测试实例,输出可能得到的最大和,每个实例的输出占一行。
 

Sample Input

    
    
1 5 7 3 8 8 1 0 2 7 4 4 4 5 2 6 5
 

Sample Output

  
  
30

#include <iostream>
using namespace std;
const int N=102;
int shuta[N][N];


int main()
{
	int C;
	cin>>C;
	while(C--)
	{
		int n;
		cin>>n;
		
		for(int i=0;i<n;i++)
			for(int j=0;j<=i;j++)
			{
				scanf("%d",&shuta[i][j]);
			}

		for(i=n-1;i>0;i--)
		{
			for(int j=0;j<i;j++)
			{
				if(shuta[i-1][j]+shuta[i][j]>shuta[i-1][j]+shuta[i][j+1])
					shuta[i-1][j]+=shuta[i][j];
				else
					shuta[i-1][j]+=shuta[i][j+1];
			}
		}
		cout<<shuta[0][0]<<endl;
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值