多重部分和 poj1742

Description

People in Silverland use coins.They have coins of value A1,A2,A3...An Silverland dollar.One day Tony opened his money-box and found there were some coins.He decided to buy a very nice watch in a nearby shop. He wanted to pay the exact price(without change) and he known the price would not more than m.But he didn‘t know the exact price of the watch.
You are to write a program which reads n,m,A1,A2,A3...An and C1,C2,C3...Cn corresponding to the number of Tony‘s coins of value A1,A2,A3...An then calculate how many prices(form 1 to m) Tony can pay use these coins.

Input

The input contains several test cases. The first line of each test case contains two integers n(1<=n<=100),m(m<=100000).The second line contains 2n integers, denoting A1,A2,A3...An,C1,C2,C3...Cn (1<=Ai<=100000,1<=Ci<=1000). The last test case is followed by two zeros.

Output

For each test case output the answer on a single line.

Sample Input

3 10
1 2 4 2 1 1
2 5
1 4 2 1
0 0

Sample Output

8
4
多重部分和问题:有n中大小不同的数字,每种c[i]个,判断这些数字之中能否选出若干个使其和为K此题是让求K<=m时,有多少个解

一个一般性的代码如下
 1 #include <cstdio>
 2 #include <cstdlib>
 3 #include <cstring>
 4 #include <iostream>
 5 #include <algorithm>
 6 using namespace std;
 7
 8 int n, m;
 9 int a[102];
10 int c[102];
11 int dp[102][100002];
12
13 int main(int argc, char const *argv[])
14 {
15     //freopen("input.txt","r",stdin);
16     while(scanf("%d %d",&n,&m) != EOF && (n != 0 && m != 0)) {
17         for(int i = 0; i < n; i++) {
18             scanf("%d",&a[i]);
19         }
20         for(int i = 0; i < n; i++) {
21             scanf("%d",&c[i]);
22         }
23         memset(dp, 0, sizeof(dp));
24         dp[0][0] = 1;
25         for(int i = 0; i < n; i++) {
26             for(int j = 0; j <= m; j++) {
27                 for(int k = 0; k <= c[i] && k * a[i] <= j;k++) {
28                     dp[i+1][j] = dp[i+1][j]| dp[i][j-k*a[i]];
29                 }
30             }
31         }
32         int ans = 0;
33         for(int i = 1; i <= m; i++) {
34             if(dp[n][i] > 0) {
35                 ans++;
36             }
37         }
38         printf("%d\n",ans);
39     }
40     return 0;
41 }

若用dp[i+1][j]表示用前i个数相加和为j时第i种数最多能剩余几个(不能得到和为-1)

可得代码如下

 1 #include <cstdio>
 2 #include <cstdlib>
 3 #include <cstring>
 4 #include <iostream>
 5 #include <algorithm>
 6 using namespace std;
 7
 8 int n, m;
 9 int a[102];
10 int c[102];
11 int dp[100002];
12
13 int main(int argc, char const *argv[])
14 {
15     //freopen("input.txt","r",stdin);
16     while(scanf("%d %d",&n,&m) != EOF && (n != 0 && m != 0)) {
17         for(int i = 0; i < n; i++) {
18             scanf("%d",&a[i]);
19         }
20         for(int i = 0; i < n; i++) {
21             scanf("%d",&c[i]);
22         }
23         memset(dp, -1, sizeof(dp));
24         dp[0] = 0;
25         for(int i = 0; i < n; i++) {
26             for(int j = 0; j <= m; j++) {
27                 if(dp[j] >= 0) {
28                     dp[j] = c[i];
29                 }
30                 else if(j < a[i] || dp[j - a[i]] <= 0) {
31                     dp[j] = -1;
32                 }
33                 else {
34                     dp[j] = dp[j - a[i]] - 1;
35                 }
36             }
37         }
38         int ans = 0;
39         for(int i = 1; i <= m; i++) {
40             if(dp[i] >= 0) {
41                 ans++;
42             }
43         }
44         printf("%d\n",ans);
45     }
46     return 0;
47 }
时间: 2024-10-11 06:42:50

多重部分和 poj1742的相关文章

POJ1742 coins 动态规划之多重部分和问题

原题链接:http://poj.org/problem?id=1742 题目大意:tony现在有n种硬币,第i种硬币的面值为A[i],数量为C[i].现在tony要使用这些硬币去买一块价格不超过m的表.他希望买的时候不用找零,问有多少种价格能满足这一点. 这个问题实际上是一个多重部分和的问题:假设有n种物品,每种物品的价值为v[i],数量为c[i],随意选取这些物品,能否使它们的价值之和恰好为m.使用动态规划的思想来求解这类问题: 定义dp数组,dp[i][j]的值代表前i种物品随意选取,价值之

编程算法 - 多重部分和问题 代码(C)

多重部分和问题 代码(C) 本文地址: http://blog.csdn.net/caroline_wendy 题目: 有n种不同大小的数字a, 每种各m个. 判断是否可以从这些数字之中选出若干使它们的和恰好为K. 使用动态规划求解(DP), 方法1: dp[i+1][j] = 用前n种数字是否能加和成j, 时间复杂度O(nKm), 不是最优. 方法2: dp[i+1][j] = 用前i种数加和得到j时, 第i种数最多能剩余多少个. 时间复杂度O(nK). 例如: n=3, a={3,5,8},

HDU1059——多重部分和问题——Dividing

Problem Description Marsha and Bill own a collection of marbles. They want to split the collection among themselves so that both receive an equal share of the marbles. This would be easy if all the marbles had the same value, because then they could

COJ 0557 4013多重部分和问题

4013多重部分和问题 难度级别:B: 运行时间限制:2000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 n种大小不同的数字 Ai,每种各Mi个,判断是否可以从这些数字之中选出若干个使他们的和恰好为K. 输入 第一行为两个正整数n,K.第二行为n个数Ai,以空格隔开.第三行为n个数Mi,以空格隔开. 输出 若可行则输出"yes"否则输出"no" 输入示例 3 173 5 83 2 2 输出示例 yes 其他说明 1<=n

14年省赛---多重部分和问题(多重背包+二进制优化)

1210: F.多重部分和问题 时间限制: 1 Sec  内存限制: 64 MB提交: 18  解决: 14 题目描述 有n种不同大小的数字,每种各个.判断是否可以从这些数字之中选出若干使它们的和恰好为K. 输入 首先是一个正整数T(1<=T<=100)接下来是T组数据 每组数据第一行是一个正整数n(1<=n<=100),表示有n种不同大小的数字 第二行是n个不同大小的正整数ai(1<=ai<=100000)第三行是n个正整数mi(1<=mi<=100000

POJ1742(多重部分和问题:模板题)

Coins Time Limit: 3000MS   Memory Limit: 30000K Total Submissions: 32776   Accepted: 11131 Description People in Silverland use coins.They have coins of value A1,A2,A3...An Silverland dollar.One day Tony opened his money-box and found there were some

POJ 1742 Coins ( 经典多重部分和问题 &amp;&amp; DP || 多重背包 )

题意 : 有 n 种面额的硬币,给出各种面额硬币的数量和和面额数,求最多能搭配出几种不超过 m 的金额? 分析 : 这题可用多重背包来解,但这里不讨论这种做法. 如果之前有接触过背包DP的可以自然想到DP数组的定义 ==> dp[i][j] 表示使用前 i 种硬币是否可以凑成面额 j . 根据这样的定义,则一开始初始化 dp[0][0] = true 最后统计 dp[n][1 ~ m] 为 true 的数量即为答案 状态转移方程为 dp[i][j] |= dp[i-1][ j - k*val[i

多重部分和问题

描述: N种不同数字ai每种mi个,判断是否可以选择若干个使得和为K N<=100,k<=100000,ai,mi<=100000,均大于零. 分析: 裸算法: DP[I][K]=0..1——前i个物品是否可以组成K for (int i=1;i<=n;i++) for (int k=0;k<=K;k++) if (Dp[i-1][k]) for (int c=0;c<=mi;c++) Dp[i][k+c*ai]=1; 时间复杂度显然是n*k*mi sum i=1..n

HDOJ1059(多重部分和问题)

#include<cstdio> #include<cstring> using namespace std; const int SIZE=120000+16; int a[6]; int dp[SIZE]; bool check() { for(int i=0;i<6;i++) if(a[i]!=0) return true; return false; } int sum; int main() { int t=0; while(true) { sum=0; for(i