数据结构——动态规划

动态规划是算法中的一个难点;
思路主要是:
1.将模型抽象,提取出数据之间的抽象关系,并且满足最优解原理;
2.满足最优解,将问题小化为子问题,转化为递推形式;

01背包问题

N=10时:

i 1 2 3 4
weight 1 3 4 5
value 2 5 6 7

对于固定容积(capacity),如何放入,价值最大?

对于这样一个问题,将其划分为若干子问题的前提是该问题符合最优解原理;
参考网络上简单的证明:采用反证法:
s[4]为记录物品装入的组合:exp:(0,1,1,0)中,1表示装入,0表示未装入;
对于容积N的背包:装入物品组合的最优解为s[v1,v2,v3,v4];
{v1,v2,v3,v4}为当前问题的最优解;
对于该背包的子问题(容积小于之前背包i=1的容积时)
{v2,v3,v4}为当前问题最优解;假设当前最优解为{z2,z3,z4}时,那么N时,最优解为v1+{z2,z3,z4};
与{v1,v2,v3,v4}相矛盾,所以该问题复合最优解原理.(即前一状态构成后续阶段决策的最后序列

满足最优解原理,该算法具有可拆分性;

F(i,j)表示对于j容量的背包,前i件物品最佳组合,所组成的最大价值;
j<w(i)时:F(i,j)=F(i-1,j);
else:
F(i,j)=max(F(i-1,j),F(i-1,j-w(i))+v(i));
F(i-1,j-w(i))+v(i)表示前i-1件在j-w(i)容量下的最优解的价值+该件物品的价值;

所以
j<w(i):F(i,j)=F(i-1,j);
j>=w(i):F(i,j)=max(F(i-1,j),F(i-1,j-w(i))+v(i));

填表j=0时,F(i,0)=0;无法装入任何物品,无价值,F(0,j)=0装入0件物品,无价值(边界条件)
w(1)=1,F(1,1)=F(0,0)+v(1)=2;
F(1,2)=F(0,1)+v(1)=2;
F(1,3)=F(0,2)+v(1)=2;

F(1,10)=F(0,9)+v(1)=2;

i j 0 1 2 3 4 5 6 7 8 9 10
0 0 0 0 0 0 0 0 0 0 0 0
1 0 2 2 2 2 2 2 2 2 2 2
2 0
3 0
4 0

i=2时:
w(2)=3
F(2,1)=F(1,1)=2;
F(2,2)=F(1,2)=2;
F(2,3)=max(F(1,3),F(1,0)+v(2))=5;
F(2,4)=max(F(1,4),F(1,1)+v(2))=7;
F(2,5)=max(F(1,5),F(1,2)+v(2))=7;

F(2,10)=max(F(1,10),F(1,7)+v(2))=7;

i j 0 1 2 3 4 5 6 7 8 9 10
0 0 0 0 0 0 0 0 0 0 0 0
1 0 2 2 2 2 2 2 2 2 2 2
2 0 2 2 5 7 7 7 7 7 7 7
3 0
4 0

i=3时:
w(3)=4
F(3,1)=F(2,1)=2;
F(3,2)=F(2,2)=2;
F(3,3)=F(2,3)=5;
F(3,4)=max(F(2,4),F(2,0)+6)=max(7,6)=7;
F(3,5)=max(F(2,5),F(2,1)+6)=max(7,8)=8;
F(3,6)=max(F(2,6),F(2,2)+6)=8;
F(3,7)=max(F(2,7),F(2,3)+6)=11;
F(3,8)=max(F(2,8),F(2,4)+6)=13;

i j 0 1 2 3 4 5 6 7 8 9 10
0 0 0 0 0 0 0 0 0 0 0 0
1 0 2 2 2 2 2 2 2 2 2 2
2 0 2 2 5 7 7 7 7 7 7 7
3 0 2 2 5 7 8 8 11 13 13 13
4 0

i=4:
w(4)=5
F(4,1)=F(3,1)=2;
F(4,2)=F(3,2)=2;
F(4,3)=F(3,3)=5;
F(4,4)=F(3,4)=7;
F(4,5)=max(F(3,5),F(3,0)+7)=max(8,7)=8;
F(4,6)=max(F(3,6),F(3,1)+7)=9;
F(4,7)=max(F(3,7),F(3,2)+7)=11;
F(4,8)=max(F(3,8),F(3,3)+7)=13;
F(4,9)=max(F(3,9),F(3,4)+7)=14;
F(4,10)=max(F(3,10),F(3,5)+7)=15;

i j 0 1 2 3 4 5 6 7 8 9 10
0 0 0 0 0 0 0 0 0 0 0 0
1 0 2 2 2 2 2 2 2 2 2 2
2 0 2 2 5 7 7 7 7 7 7 7
3 0 2 2 5 7 8 8 11 13 13 13
4 0 2 2 5 7 8 9 11 13 14 15

采用递归方法:

接口:


public interface Bag {
	
	public int MaxFound(int i,int capacity);

}

节点类

public class Node {
		private int weight;
		private int value;
		
		Node(int weight,int value)
		{
			this.weight=weight;
			this.value=value;
		}
		public int Getweight()
		{
			return weight;
		}
		public int Getvalue()
		{
			return value;
		}
	}




import java.util.Scanner;

public class Bagimp implements Bag{
	
	private int size;
	private int number;
	private Node[] list;
	
	
	Bagimp()
	{		
		Scanner sc=new Scanner(System.in);		
		System.out.println("Input the capacity:");
		size=sc.nextInt();
		System.out.println("Input the number of craft:");
		number=sc.nextInt();
		list=new Node[number+1];
	}
	
	public int getNumber()
	{
		return number;
	}
	
	public int getSize()
	{
		return size;
	}
	public void InputValue()
	{
		Scanner sc=new Scanner(System.in);
		int weight,value;
		for(int i=1;i<=number;i++)
		{
			weight=sc.nextInt();
			System.out.println("*----*");
			value=sc.nextInt();
			list[i]=new Node(weight,value);
		}
	}
	
	//递归算法
	public int MaxFound(int i,int capacity)
	{
		if(i<1||capacity<=0)
		{
			return 0;
		}
		else
		{
			int maxSum;
			if(list[i].Getweight()>capacity)
			{
				maxSum=MaxFound(i-1,capacity);
			}
			else
			{
				maxSum=Math.max(MaxFound(i-1,capacity),(MaxFound(i-1,capacity-list[i].Getweight())+list[i].Getvalue()));
			}
			return maxSum;
		}
	}
	
	public void display()
	{
		int Finalfound=MaxFound(number,size);
		System.out.println(Finalfound);
	}
	

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Bagimp s=new Bagimp();
		s.InputValue();
		s.display();
	}


}

输入背包容量10;物品个数4;每件物品所对应的重量,价值如初始表所示:

Input the capacity:
10
Input the number of craft:
4
1
*----*
2
3
*----*
5
4
*----*
6
5
*----*
7

result:
在这里插入图片描述
使用动态规划降低复杂度:
使用辅助数组,自下至上记录当前步骤的最大值;
空间复杂度为O(nnumber),时间复杂度为O(nnumber);

	//递归空间复杂度过高,呈指数形式递增,采用动规方法降低复杂度
	public int MaxFound()
	{
		int [][] assist=new int[number+1][size+1];//辅助数组记录
		//字底向上遍历
		for(int i=0;i<=number;i++)
		{
			for(int j=0;j<=size;j++)
			{
				if(i==0||j==0)
				{
					assist[i][j]=0;//边界条件;
				}
				else if(list[i].Getweight()>j)
				{
					assist[i][j]=assist[i-1][j];
				}
				else
				{
					assist[i][j]=Math.max(assist[i-1][j], (assist[i-1][j-list[i].Getweight()]+list[i].Getvalue()));
				}
			}
		}
		return assist[number][size];
	}

猜你喜欢

转载自blog.csdn.net/qq_42378434/article/details/87970589