C语言算法训练 - 装箱问题_动态规划问题(有一个箱子容量为V(正整数,0<=V<=20000),同时有n个物品(0<n<=30),每个物品有一个体积(正整数))

问题描述

有一个箱子容量为V(正整数,0<=V<=20000),同时有n个物品(0<n<=30),每个物品有一个体积(正整数)。
  要求n个物品中,任取若干个装入箱内,使箱子的剩余空间为最小。
输入格式
  第一行为一个整数,表示箱子容量;
  第二行为一个整数,表示有n个物品;
  接下来n行,每行一个整数表示这n个物品的各自体积。
输出格式
  一个整数,表示箱子剩余空间。
例子

样例输入
24
6
8
3
12
7
9
7
样例输出
0

思路

可设一个元素个数为 max(v)+1的数组dp[20001],里面任意一个元素dp[i]表示箱子容积为 i 时可放入的物品的体积。因为物品的体积并不是单位体积,因此dp[i]并不一定等于 i,例如有3个物体,体积分别为3,4,5,那么容积为3和4的箱子可放入的物品的体积均为3,即dp[3] = dp[4] = 3。对于每一个物体,都有两种选择-放入或者不放入,所以外层循环可对每个物品进行遍历,而每选择一个物品,定会对大于该物品体积的dp数组元素产生影响,从而还需要一个内层数组对大于该物品体积的dp数组元素进行遍历更新。更新方法为:dp[i] = max{ dp[i] , dp[i - vi]+vi },其中vi为当前物品的体积,max中的dp[i]表示不放入该物体时的解, dp[i - vi]+vi表示放入该物体时的解(i-vi表示给即将放入的物品留出合适的体积,如之前的例子,dp[i-vi]并不一定等于dp[i] - vi),取最大值,即为最优解。需要注意的是,需要先将dp数组中的每一个元素初始化为0。

#include 
int V;//箱子体积 
int n;//个数 
int a[31];  //存放物品的体积 
int dp[20001]={
     0};  //dp[i]表示箱子容积为i时可放入的物品的体积 ,注意要初始化为0 

int main ()
{
     
    int i,j;
    int t;
	scanf("%d",&V);
	scanf("%d",&n);
    
	for(i=0;i<n;i++)
		scanf("%d",&a[i]);
	
	for(i=0;i<n;i++)//外循环,遍历每个箱子 
	{
     
		for(j=V;j>=a[i];j--)//内循环,遍历每个容积 
		{
     
			if(dp[j]>( dp[j-a[i]]+a[i] ))
			   dp[j]=dp[j];
			else
				dp[j]=dp[j-a[i]]+a[i];  //取最大值,最优解 
			
		}
	}	
    printf("%d",V-dp[V]);  //输出最小的容积 
    return 0;
}

运行示例
C语言算法训练 - 装箱问题_动态规划问题(有一个箱子容量为V(正整数,0<=V<=20000),同时有n个物品(0<n<=30),每个物品有一个体积(正整数))_第1张图片

你可能感兴趣的:(c语言,算法)