标签:
Description
Input
Output
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 }
标签:
原文地址:http://www.cnblogs.com/jasonJie/p/5790170.html