洛谷 P3052

题目链接

点我跳转

题目大意

给出 \(n\) 个物品,第 \(i\) 个物品体积为 \(w_i\),现把其分成若干组,要求每组总体积 \(<=W\),问最小分组。\((n<=18)\)

解题思路

\(dp[i]\) 表示当前状态为 \(i\) 的最少分组数

\(sum[i]\) 表示把当前状态的所有人分到一个组需要的容量

\(sum[j] <= K\) 时,可以把状态 \(j\)(\(j\)\(i\)的子集) 的所有人分到一组,那么 \(dp[i] = min(dp[i] , dp[i - j] + 1)\)

AC_Code

#include<bits/stdc++.h>
using namespace std;
int dp[1 << 19] , sum[1 << 19];
int n , k , a[20];
signed main()
{
	memset(dp , 0x3f , sizeof(dp));
	dp[0] = 0;
	cin >> n >> k;
	for(int i = 1 ; i <= n ; i ++) cin >> a[i];
	for(int i = 1 ; i < (1 << n) ; i ++) 
	{
		for(int j = 1 ; j <= n ; j ++)
		{
			if(1 << (j - 1) & i) sum[i] += a[j];
		}
	}
	for(int i = 1 ; i < (1 << n) ; i ++)
	{
		for(int j = i ; j ; j = (j - 1) & i)
		{
			if(sum[j] > k) continue ;
			dp[i] = min(dp[i] , dp[i - j] + 1);
		}
	}
	cout << dp[(1 << n) - 1] << '\n';
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值