洛谷1049 装箱问题

题目:装箱问题


思路:

dp。

bool f[i][j]表示取前i个物品能否恰好占用j个空间。

转移方程f[i][j]=f[i-1][j-w[i]] | f[i-1][j]

最开始maxm和maxn的数值写反了……Wa了好久。


代码:

#include<bits/stdc++.h>
using namespace std;

#define maxm 20000
#define maxn 30

int m,n;
int w[maxn+5]= {0};
bool f[maxn+5][maxm+5]= {0};

int main() {
	scanf("%d%d",&m,&n);
	for(int i=1; i<=n; i++) {
		scanf("%d",&w[i]);
	}
	f[0][0]=true;
	for(int i=1; i<=n; i++) {
		for(int j=m; j>=w[i]; j--) {
			if(f[i-1][j-w[i]]) f[i][j]=true;
		}
		for(int j=m;j>=0;j--) f[i][j]|=f[i-1][j];
	}
	for(int j=m; j>=0; j--)
		if(f[n][j]) {
			printf("%d",m-j);
			break;
		}
	return 0;
}

### 动态规划装箱问题中的应用 装箱问题是典型的 **0/1 背包问题** 的变种之一。其核心在于如何利用有限的空间装载尽可能多的物品,或者使剩余空间最小化。此问题可以采用动态规划的思想来解决。 #### 问题描述 假设有一个箱子容量为 \( V \),以及若干个不同大小的物品,每个物品只能放入一次(即 0/1 背包)。目标是找到一种方案使得所选物品的总体积最接近于 \( V \) 并不超过它。 --- #### 解题思路 动态规划的核心思想是将大问题分解为多个子问题并存储中间结果以避免重复计算[^1]。对于装箱问题: - 定义状态数组 `dp[j]` 表示当背包容量为 \( j \) 时能够容纳的最大体积。 - 初始化:设初始状态下背包为空,则 `dp[0] = 0`;其余位置初始化为负无穷或零视具体需求而定。 - 状态转移方程: \[ dp[j] = \max(dp[j], dp[j - w_i] + w_i),\quad (w_i \leq j) \] 这里的 \( w_i \) 是第 \( i \) 件物品的重量(或体积)。 上述公式的含义是在当前考虑的物品下,判断是否将其加入到已有的最佳组合中去形成新的更优解。 由于题目要求的是最终未被填满的部分最少,因此最后一步还需要计算差值作为答案输出。 以下是基于以上逻辑编写的 Java 版本程序实现: ```java import java.util.Scanner; public class PackingProblem { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); // 输入数据读取 System.out.println("请输入容器最大容量V 和 物品数量N:"); int V = scanner.nextInt(); // 总体积极限 int N = scanner.nextInt(); // 物品种类数目 int[] weights = new int[N + 1]; for (int i = 1; i <= N; ++i){ weights[i] = scanner.nextInt(); } // 创建DP表,默认填充为0 int[] dp = new int[V + 1]; // 开始迭代更新DP表格 for (int i = 1; i <= N; ++i){ for (int j = V; j >= weights[i]; --j){ dp[j] = Math.max(dp[j], dp[j - weights[i]] + weights[i]); } } // 输出结果 System.out.println(V - dp[V]); // 剩余空间量 } } ``` 该代码实现了基本的功能框架,并遵循了标准输入输出模式以便测试不同的案例集。 --- #### 关键点解析 1. **逆序遍历的原因** 对于每一件新增加的商品,在更新整个dp数组的时候采取倒叙方式是为了防止前面已经处理过的商品再次影响本次循环的结果造成错误覆盖情况发生[^2]。 2. **时间复杂度分析** 外层循环执行次数取决于物品总数\( n \),内层则依赖于背包容量\( m \),所以整体的时间复杂度大约为O(nm)[^1]. 3. **边界条件处理** 需要注意一些特殊情况下的行为定义,例如如果没有任何东西能放进背包里怎么办?此时应该返回原始容量本身表示完全没用上任何资源。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值