COJ 0557 4013多重部分和问题

4013多重部分和问题
难度级别:B; 运行时间限制:2000ms; 运行空间限制:262144KB; 代码长度限制:2000000B

试题描述

n种大小不同的数字 Ai,每种各Mi个,判断是否可以从这些数字之中选出若干个使他们的和恰好为K。

输入

第一行为两个正整数n,K。
第二行为n个数Ai,以空格隔开。
第三行为n个数Mi,以空格隔开。

输出

若可行则输出"yes"
否则输出"no"

输入示例

3 17
3 5 8
3 2 2

输出示例

yes

其他说明

1<=n<=100
1<=K<=50000
1<=Ai<=40
1<=Mi<=50

若数字相同对程序并无影响。

题解:此题有四个层次:

1.枚举bool乱搞:

 1 //标程4
 2 #include<iostream>
 3 #include<cstdio>
 4 #include<cmath>
 5 #include<algorithm>
 6 #include<queue>
 7 #include<cstring>
 8 #define PAU putchar(‘ ‘)
 9 #define ENT putchar(‘\n‘)
10 using namespace std;
11 const int maxn=100+10,maxm=50000+10,inf=-1u>>1;
12 bool d[maxn][maxm];int n,tar,A[maxn],num[maxn];
13 inline int read(){
14     int x=0,sig=1;char ch=getchar();
15     while(!isdigit(ch)){if(ch==‘-‘) sig=-1;ch=getchar();}
16     while(isdigit(ch)) x=10*x+ch-‘0‘,ch=getchar();
17     return x*=sig;
18 }
19 inline void write(int x){
20     if(x==0){putchar(‘0‘);return;}if(x<0) putchar(‘-‘),x=-x;
21     int len=0,buf[15];while(x) buf[len++]=x%10,x/=10;
22     for(int i=len-1;i>=0;i--) putchar(buf[i]+‘0‘);return;
23 }
24 void init(){
25     memset(d,false,sizeof(d));
26     n=read();tar=read();
27     for(int i=0;i<n;i++) A[i]=read();
28     for(int i=0;i<n;i++) num[i]=read();
29     return;
30 }
31 void work(){
32     d[0][0]=true;
33     for(int i=0;i<n;i++)
34         for(int j=0;j<=tar;j++)
35             for(int k=0;k<=num[i]&&k*A[i]<=j;k++)
36                 d[i+1][j]|=d[i][j-k*A[i]];
37     if(d[n][tar]) puts("yes");
38     else puts("no");
39     return;
40 }
41 void print(){
42     return;
43 }
44 int main(){
45     init();work();print();return 0;
46 }

2.快看窝萌还可以滚动,好神奇!

 1 //标程3
 2 #include<iostream>
 3 #include<cstdio>
 4 #include<cmath>
 5 #include<algorithm>
 6 #include<queue>
 7 #include<cstring>
 8 #define PAU putchar(‘ ‘)
 9 #define ENT putchar(‘\n‘)
10 using namespace std;
11 const int maxn=100+10,maxm=50000+10,inf=-1u>>1;
12 bool d[2][maxm];int n,tar,A[maxn],num[maxn];
13 inline int read(){
14     int x=0,sig=1;char ch=getchar();
15     while(!isdigit(ch)){if(ch==‘-‘) sig=-1;ch=getchar();}
16     while(isdigit(ch)) x=10*x+ch-‘0‘,ch=getchar();
17     return x*=sig;
18 }
19 inline void write(int x){
20     if(x==0){putchar(‘0‘);return;}if(x<0) putchar(‘-‘),x=-x;
21     int len=0,buf[15];while(x) buf[len++]=x%10,x/=10;
22     for(int i=len-1;i>=0;i--) putchar(buf[i]+‘0‘);return;
23 }
24 void init(){
25     memset(d,false,sizeof(d));
26     n=read();tar=read();
27     for(int i=0;i<n;i++) A[i]=read();
28     for(int i=0;i<n;i++) num[i]=read();
29     return;
30 }
31 void work(){
32     int tc=0;d[tc][0]=true;
33     for(int i=0;i<n;i++){
34         tc^=1;
35         for(int j=0;j<=tar;j++)
36             for(int k=0;k<=num[i]&&k*A[i]<=j;k++)
37                 d[tc][j]|=d[tc^1][j-k*A[i]];
38     }
39     if(d[tc][tar]) puts("yes");
40     else puts("no");
41     return;
42 }
43 void print(){
44     return;
45 }
46 int main(){
47     init();work();print();return 0;
48 }

3.窝萌还可以搞出正好凑成k的:

 1 //标程2
 2 #include<iostream>
 3 #include<cstdio>
 4 #include<cmath>
 5 #include<algorithm>
 6 #include<queue>
 7 #include<cstring>
 8 #define PAU putchar(‘ ‘)
 9 #define ENT putchar(‘\n‘)
10 using namespace std;
11 const int maxn=100+10,maxm=50000+10,inf=-1u>>1;
12 int d[2][maxm],n,tar,A[maxn],num[maxn];
13 inline int read(){
14     int x=0,sig=1;char ch=getchar();
15     while(!isdigit(ch)){if(ch==‘-‘) sig=-1;ch=getchar();}
16     while(isdigit(ch)) x=10*x+ch-‘0‘,ch=getchar();
17     return x*=sig;
18 }
19 inline void write(int x){
20     if(x==0){putchar(‘0‘);return;}if(x<0) putchar(‘-‘),x=-x;
21     int len=0,buf[15];while(x) buf[len++]=x%10,x/=10;
22     for(int i=len-1;i>=0;i--) putchar(buf[i]+‘0‘);return;
23 }
24 void init(){
25     memset(d,-1,sizeof(d));
26     n=read();tar=read();
27     for(int i=0;i<n;i++) A[i]=read();
28     for(int i=0;i<n;i++) num[i]=read();
29     return;
30 }
31 void work(){
32     int tc=0;d[tc][0]=0;
33     for(int i=0;i<n;i++){
34         tc^=1;
35         for(int j=0;j<=tar;j++){
36             if(d[tc^1][j]>=0) d[tc][j]=num[i];
37             else if((j>=A[i]&&d[tc][j-A[i]]>=0)&&d[tc^1][j]) d[tc][j]=d[tc][j-A[i]]-1;
38             else d[tc][j]=-1;
39         }
40     }
41     if(d[tc][tar]>=0) puts("yes");
42     else puts("no");
43     return;
44 }
45 void print(){
46     return;
47 }
48 int main(){
49     init();work();print();return 0;
50 }

4.快看窝萌还可以滚动,好神奇!

 1 //标程1
 2 #include<iostream>
 3 #include<cstdio>
 4 #include<cmath>
 5 #include<algorithm>
 6 #include<queue>
 7 #include<cstring>
 8 #define PAU putchar(‘ ‘)
 9 #define ENT putchar(‘\n‘)
10 using namespace std;
11 const int maxn=100+10,maxm=50000+10,inf=-1u>>1;
12 int d[maxm],n,tar,A[maxn],num[maxn];
13 inline int read(){
14     int x=0,sig=1;char ch=getchar();
15     while(!isdigit(ch)){if(ch==‘-‘) sig=-1;ch=getchar();}
16     while(isdigit(ch)) x=10*x+ch-‘0‘,ch=getchar();
17     return x*=sig;
18 }
19 inline void write(int x){
20     if(x==0){putchar(‘0‘);return;}if(x<0) putchar(‘-‘),x=-x;
21     int len=0,buf[15];while(x) buf[len++]=x%10,x/=10;
22     for(int i=len-1;i>=0;i--) putchar(buf[i]+‘0‘);return;
23 }
24 void init(){
25     memset(d,-1,sizeof(d));
26     n=read();tar=read();
27     for(int i=0;i<n;i++) A[i]=read();
28     for(int i=0;i<n;i++) num[i]=read();
29     return;
30     return;
31 }
32 void work(){
33     d[0]=0;
34     for(int i=0;i<n;i++){
35         for(int j=0;j<=tar;j++){
36             if(d[j]>=0) d[j]=num[i];
37             else if((j>=A[i]&&d[j-A[i]]>=0)&&d[j]) d[j]=d[j-A[i]]-1;
38             else d[j]=-1;
39         }
40     }
41     if(d[tar]>=0) puts("yes");
42     else puts("no");
43     return;
44 }
45 void print(){
46     return;
47 }
48 int main(){
49     init();work();print();return 0;
50 }

结论:然并卵。

时间: 2024-08-07 04:31:55

COJ 0557 4013多重部分和问题的相关文章

编程算法 - 多重部分和问题 代码(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

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

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 pri

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种物品随意选取,价值之

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

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

多重部分和问题

描述: 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