bzoj-2287___POJ Challenge —— 删除背包

题目链接:传送门(原题目好像在OJ上消失了,真是诡异)

题目大意:

  简单的背包,问第 i i i个物品消失( i i i 1 1 1 n n n),装满容积为 x x x的背包的方案数( x x x 1 1 1 m m m),输出 i i i m m m的矩阵

解题思路:

  一开始简单的想从 1 1 1遍历到 n n n去算第 i i i个物品消失的影响,但在仔细一想发现不对经。后来想了一下发现应该用再用一次dp来优化复杂度,即先求出物品不消失的所有背包方案数,然后再遍历依次求每个物品消失时,背包方案数。

代码思路:

  先01背包套个模板,然后物品依次消失的时候,这里和01背包思想不一样
   ① ① 当容量 j < w [ i ] j<w[i] j<w[i]时,很明显总方案数就是当前容量 j j j的方案数
   ② ② 但当容量 j > = w [ i ] j>=w[i] j>=w[i]时,当前容量 j j j的方案数就等于总方案数 − - 容量 j − w [ i ] j-w[i] jw[i]的方案数
  这样来判断时,我们的容量 j j j就要从 1 1 1遍历到 m m m,因为每次转移时要从没有这个物品的状态转移

核心:很经典的双重dp,理解好了可以加深dp的思想

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e3 + 5;
int n, m;
int w[maxn], v[maxn];
int dp[maxn][maxn], all[maxn];

int main() {
	scanf("%d%d", &n, &m);
	for(int i=0; i<n; i++)
		scanf("%d", &w[i]);
	memset(dp, 0, sizeof(dp));

	for(int i=0; i<n; i++) {
		all[0] = 1;
		for(int j=m; j>=w[i]; j--) {
			all[j] += all[j - w[i]];
			all[j] %= 10;
		}
	}

	for(int i=0; i<n; i++) {
		dp[i][0] = 1;
		for(int j=1; j<=m; j++)
			if(j>=w[i]) {
				dp[i][j] = all[j] - dp[i][j-w[i]] + 10;
				dp[i][j] %= 10;
			} else {
				dp[i][j] = all[j];
			}
	}

	for(int i=0; i<n; i++) {
		for(int j=1; j<=m; j++)
			printf("%d", dp[i][j]);
		printf("\n");
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值