深度优先搜索和01背包的综合题,数据不大,很中规中矩
砝码称重
题目描述
现有 n n n 个砝码,重量分别为 a i a_i ai,在去掉 m m m 个砝码后,问最多能称量出多少不同的重量(不包括 0 0 0)。
请注意,砝码只能放在其中一边。
输入格式
第 1 1 1 行为有两个整数 n n n 和 m m m,用空格分隔。
第 2 2 2 行有 n n n 个正整数 a 1 , a 2 , a 3 , … , a n a_1, a_2, a_3,\ldots , a_n a1,a2,a3,…,an,表示每个砝码的重量。
输出格式
仅包括 1 1 1 个整数,为最多能称量出的重量数量。
样例 #1
样例输入 #1
3 1
1 2 2
样例输出 #1
3
提示
【样例说明】
在去掉一个重量为 2 2 2 的砝码后,能称量出 1 , 2 , 3 1, 2, 3 1,2,3 共 3 3 3 种重量。
【数据规模】
对于 20 % 20\% 20% 的数据, m = 0 m=0 m=0。
对于 50 % 50\% 50% 的数据, m ≤ 1 m\leq 1 m≤1。
对于 50 % 50\% 50% 的数据, n ≤ 10 n\leq 10 n≤10。
对于
100
%
100\%
100% 的数据,
n
≤
20
n\leq 20
n≤20,
m
≤
4
m\leq 4
m≤4,
m
<
n
m < n
m<n,
a
i
≤
100
a_i\leq 100
ai≤100。
题目链接
代码部分:
#include<bits/stdc++.h>//万能头文件
using namespace std;
#define N 100005
int n,m,x,ret=0,ans=0,W,a[N],w[N];//ret为单次dp中的值,ans为总体最优值
bool f[N];
void dp() {
memset(f,0,sizeof(f));
f[0]=1;
ret=0;
for(int i=1; i<=m; i++)
for(int j=W; j>=w[i]; j--) {
if(f[j-w[i]]&&!f[j]) {
f[j]=1;
ret++;
}
}
} //01背包dp部分
void dfs(int pos,int js) {
if(js==m) {
dp();
ans=max(ans,ret);
return;
}
for(int i=pos+1; i<=n; i++) {
w[js+1]=a[i];
dfs(i,js+1);
}
}//深搜部分
int main() {
cin>>n>>m;
m=n-m;
for(int i=1; i<=n; i++) {
cin>>a[i];
W+=a[i];
}
dfs(0,0);
cout<<ans;
return 0;
}