题目描述
现有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 }