思路:
1.搜索参数:当前已经选取的个数;已经放弃的个数
2.搜索剪枝:放弃的比m多,则return
3.搜索边界:如果已选取了n个:如果正好放弃了m个,dp;return
3.搜索内容:(1)不放弃当前砝码
(2)放弃当前砝码
4.标记:是否被放弃
5.DP:利用背包解决
代码:
#include <iostream> #include <cstring> using namespace std; const int MAXN = 2010; int n, m, ans; int a[MAXN], vis[MAXN], f[MAXN]; void dp() { memset(f, 0, sizeof(f)); f[0] = 1; int ret = 0, sum = 0; for(int i=0; i<=n; i++) { if(vis[i]) continue; for(int j=sum; j>=0; j--) { if(f[j] && !f[j + a[i]]) { f[j + a[i]] = 1; ret ++; } } sum += a[i]; } ans = max(ans, ret); } void dfs(int get, int give_up) { if(give_up > m) { return ; } if(get == n) { if(give_up == m) { dp(); } return ; } dfs(get + 1, give_up); vis[get] = 1; dfs(get + 1, give_up + 1); vis[get] = 0; } int main() { cin >> n >> m; for(int i=0; i<n; i++) { cin >> a[i]; } dfs(0, 0); cout << ans << endl; return 0; }