01背包问题 (好难理解)

 算法提升 01背包  
时间限制:1.0s   内存限制:256.0MB
    
问题描述
  给定N个物品,每一个物品有一个重量W和一个价值V.你有一个能装M重量的背包.问怎么装使得所装价值最大.每一个物品只有一个.
输入格式
  输入的第一行包含两个整数n, m,分别表示物品的个数和背包能装重量。
  之后N行每行两个数Wi和Vi,表示物品的重量和价值
输出格式
  输出1行,包含一个整数,表示最大价值。
样例输入
3 5
2 3
3 5
4 7
样例输出
8
数据规模和约定
  1<=N<=200,M<=5000.
//01背包问题
#include<iostream>
#include<string.h>
using namespace std;
int dp[220][5500];
int max(int a,int b)
{
	if(a>b)
		return a;
	else
		return b;
}
int main()
{
	int n,m;//n:背包数目 m:最大容量
	cin>>n>>m;
	int i,j,w[220],v[220];//w[i]重量(可理解为第i个背包容量) ,v[i]价值
	for(i=1;i<=n;i++)//下标从1记录方便理解
	{
		cin>>w[i]>>v[i];
	}
	//动态规划dp[i][j] 记录 用j总容量去背起前i个背包中的若干个背包 的最大价值
	//将用j总容量背起前i个背包中若干个背包的问题变为:背第i个背包+用剩余容量j-w[i]去背起前i-1个背包中的若干个背包.
	//即dp[i][j]=v[i]+dp[i-1][j-w[i]];另外还有一种考虑不背第i个背包的即为:dp[i][j]=dp[i-1][j];
	//到此2种状况要判断取最大,故得出状态转移方程:dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+v[i]);
	//可见求前i个背包用j容量的最大价值须要先知道dp[i-1][j]和dp[i-1][j-w[i]]这2个值已经在计算i的前算出.
	memset(dp,0,sizeof(dp));
	for(i=1;i<=n;i++)
	{
		for(j=1;j<=m;j++)
		{
			dp[i][j]=max(dp[i][j],dp[i-1][j]);
			if(j-w[i]>=0)
				dp[i][j]=max(dp[i][j],dp[i-1][j-w[i]]+v[i]);
		}
	}
	cout<<dp[n][m]<<endl;
	return 0;
}