0-1背包问题(C++ && 详解)DP

其实一直觉得这个题目很蛋疼,因为看了N遍,也写了N遍,但是过1一个月后,再独立思考还是很难想到(传说中的智商吗?)

在网上看了好几个帖子,觉得对递归式的表述不够通俗
好吧,看看我是怎么理解的吧
令V[i][v]表示考虑“前i个物品,最大可用空间为v”的情况下,可以装的物品的总价值
注:前i个物品到底选哪几个,从这个公式是看不出来的;最大空间为v,有可能没装满
则有递归optimal式子:V[i][v]=V[i-1][v] ----- weigh[i] > v;(1)
V[i][v]=Max( V[i-1][v],V[i-1][ v-weigh[i] ] ) (2)
(1)表示:若把箱子清空(把原来所有物品都倒了),然后把i物品放进去(就放一个哦),都放不下,在这种情况下,必然V[i][v]还是和V[i-1][v]
(2)表示:如果i物品一个人能住得下v的体积的话,那我就干脆腾出一些地方满足i,所以腾出地方后剩下了v-weigh[i];看看i入住之后,箱子内的总价值到底增多了还是少了,少了就保持原来的(i滚蛋),多了就让i进入
关于打印路径:
0 1 2 3 4 5
0 :0 0   0   0   0   0
1 :0 0   0   0   0   0
2 :0 6   6   6   6   6
3 :0 6   6   6   6   6
4 :0 6   9   9   9   9
5 :0 6   9   9   9   9
6 :0 6   9   9   9   12
7 :0 6   9   9   10   12
8 :0 6   9   11   11   15
9 :0 6   9   11   13   15
10:0 6   9   14   14   15
比较直观,开始指针指向p[10][5],也就是最右下角
假设,此时指针指向p[i][v]然后往左,如果左边的跟他不等,说明在写这个位置的数字时,是选择了递归optimal式子中的2,也就是说用了i物品
此时打印出i物品,然后将指针指向p[i-1][v-weigh[i]],然后继续loop
如果左边跟他相等(例如p[6][4]==p[6][3]),说明在写这个位置的时候,选择了递归optimal式子中的1,也就说i物品没有加进来,此吃将i--就行了,然后继续loop

直到i==0打印路径结束


void main()
{
	const int N=5;//物品的个数
	const int M=10;//背包能装东西的总重量
	int weigh[N+1] = {0,2,2,6,5,4};//物品重量 or 体积
	int value[N+1] = {0,6,3,5,4,6};//物品价值


	int V[N+1][M+1];
	
	//初始化,表格边缘初始化为0
	for(int i=0;i<=M;i++)
		V[0][i]=0;
	for(int i=0;i<=N;i++)
		V[i][0]=0;
	//region 开始DP
	for(int i=1;i<=N;i++)//i 是物品的index
	{
		for( int v=1; v<=M; v++ )// 是当前讨论的体积
		{
			V[i][v] = V[i-1][v];
			if ( weigh[i] <= v )//目前讨论的体积能装的下第i个物品
			{
				//如果拿掉一些剩下体积v-weigh[i]时,再装入i物品,是否能多装一些
				V[i][v] = V[i][v] > V[ i-1 ][ v-weigh[i] ]+value[i] ? V[i][v] : V[ i-1 ][ v-weigh[i] ]+value[i] ;
			}
		}
	}
	//endregion 结束DP

	//将结果打印出来看看

	for(int v=1;v<=M;v++)
	{
		cout<<v<<" : ";
		for(int i=1;i<=N;i++)
		{
			cout<<V[i][v]<<"   ";
		}
		cout<<endl;
	}

	//寻找那些物品需要带走,即,寻找路径
	int ii=N,jj=M;
	while(ii>0)
	{
		if( V[ii][jj]>V[ii-1][jj] )
		{
			cout<<ii<<" ";
			jj-=weigh[ii];
			ii--;

		}
		else if(V[ii][jj] == V[ii-1][jj] )
			ii--;
		else
		{
			cout<<"error"<<endl;
			throw new exception("错啦");
		}
	}
	
}












   

你可能感兴趣的:(C++,exception)