POJ 1742 dp

题意

传送门 POJ 1742

多重部分和问题

d p [ i + 1 ] [ j ] : = 用 前 i 种 数 加 和 得 到 j 时 第 i 种 数 最 多 能 剩 余 多 少 个 ( 不 能 加 和 得 到 j 的 情 况 下 为 − 1 ) dp[i+1][j]:=用前i种数加和得到j时第i种数最多能剩余多少个(不能加和得到j的情况下为-1) dp[i+1][j]:=ijij1

实现上重复利用数组,最终满足 d p [ i ] ≥ 0 , i > 0 dp[i]\geq 0,i>0 dp[i]0,i>0 i i i 的数量即答案。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <queue>
#define min(a,b)    (((a) < (b)) ? (a) : (b))
#define max(a,b)    (((a) > (b)) ? (a) : (b))
#define abs(x)    ((x) < 0 ? -(x) : (x))
#define INF 0x3f3f3f3f
#define delta 0.85
#define eps 1e-3
#define PI 3.14159265358979323846
#define MAX_N 105
#define MAX_M 100005
using namespace std;
typedef pair<int, int> P;
int N, M;
int A[MAX_N], C[MAX_N];
int dp[MAX_M];

int main(){
	while(~scanf("%d%d", &N, &M) && (N | M)){
		memset(dp, -1, sizeof(dp));
		for(int i = 0; i < N; i++) scanf("%d", A + i);
		for(int i = 0; i < N; i++) scanf("%d", C + i);
		dp[0] = 0;
		for(int i = 0; i < N; i++){
			for(int j = 0; j <= M; j++){
				if(dp[j] >= 0) dp[j] = C[i];
				else if(j < A[i] || dp[j - A[i]] <= 0) dp[j] = -1;
				else dp[j] = dp[j - A[i]] - 1;
			}
		}
		int res = 0;
		for(int i = 1; i <= M; i++) if(dp[i] >= 0) ++res;
		printf("%d\n", res);
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值