洛谷P1441 砝码称重

题目描述

现有n个砝码,重量分别为a1,a2,a3,……,an,在去掉m个砝码后,问最多能称量出多少不同的重量(不包括0)。

输入输出格式

输入格式:

输入文件weight.in的第1行为有两个整数n和m,用空格分隔

第2行有n个正整数a1,a2,a3,……,an,表示每个砝码的重量。

输出格式:

输出文件weight.out仅包括1个整数,为最多能称量出的重量数量。

这道题是洛谷P2347 砝码称重的加强版,需要先搜索去除m个砝码,再运用01背包

其实本题与洛谷P2347 砝码称重看上去都像是多重背包,但多重背包可以通过拆分化为01背包问题,最实用的我认为应该是二进制拆分了,但由于我现在实在不会这个东西,以后那天我会了我再来补上这张锅吧。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cstdlib>
 6 using namespace std;
 7 #define maxn 10010
 8 #define ll long long
 9 #define IL inline
10 #define clear(a) memset(a,0,sizeof a)
11 IL void read(int &x)
12 {
13     x = 0;int f = 1;char ch = getchar();
14     while(ch<'0'||ch>'9'){if(ch=='-')f = -f;ch = getchar();}
15     while(ch>='0'&&ch<='9'){x = x * 10 + ch - '0', ch = getchar();}x *= f;
16 }
17 
18 int n, m, ans, tot, sum;
19 int a[maxn], col[maxn], f[maxn], pre[maxn];
20 
21 int dp()
22 {
23     sum = 0;
24     tot = 0;
25     clear(pre), clear(f);
26     for (int i = 1; i <= n;i++)
27         if(!col[i])
28         {
29             pre[++tot] = a[i];
30             sum += a[i];
31         }
32     f[0] = 1;
33     for (int i = 1; i <= tot;i++)
34         for (int j = sum; j >= pre[i];j--)
35             f[j] += f[j - pre[i]];
36     int total = 0;
37     for (int i = 1; i <= sum;i++)
38         if(f[i])
39             total++;
40     return total;
41 }
42 
43 void dfs(int cth,int away)
44 {
45     if(away>m)return; 
46     if(cth==n)
47     {
48         if(away==m)
49             ans=max(ans,dp());
50         return;
51     }
52     dfs(cth + 1, away);
53     col[cth+1] = 1;
54     dfs(cth + 1, away + 1);
55     col[cth+1] = 0;
56 }
57 
58 int main()
59 {
60     read(n), read(m);
61     for (int i = 1; i <= n;i++)
62         read(a[i]);
63     dfs(0, 0);
64     cout << ans;
65     return 0;
66 }

猜你喜欢

转载自www.cnblogs.com/KGW-/p/10367407.html