原题链接
挺水的一道题。
(DFS)枚举被删除的砝码,每次删完后进行(01)背包计数,取最大值即可。
这题不需要剪枝即可通过。
我这里是用链表储存的数据。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 25;
const int M = 2010;
struct dd {
int x, pre, suc;
};
dd a[N];
int f[M], n, m, ma, s;
inline int re()
{
int x = 0;
char c = getchar();
bool p = 0;
for (; c < '0' || c > '9'; c = getchar())
p |= c == '-';
for (; c >= '0' && c <= '9'; c = getchar())
x = x * 10 + c - '0';
return p ? -x : x;
}
inline int maxn(int x, int y)
{
return x > y ? x : y;
}
bool comp(dd x, dd y)
{
return x.x < y.x;
}
void de(int x)
{
a[a[x].pre].suc = a[x].suc;
a[a[x].suc].pre = a[x].pre;
}
void con(int x)
{
a[a[x].pre].suc = x;
a[a[x].suc].pre = x;
}
int calc()
{
int i, j, k = 0;
memset(f, 0, sizeof(f));
f[0] = 1;
for (i = a[0].suc; i <= n; i = a[i].suc)
for (j = s; j >= a[i].x; j--)
if (!f[j] && f[j - a[i].x])
{
f[j] |= f[j - a[i].x];
k++;
}
return k;
}
void dfs(int x, int nw)
{
if (!(nw ^ m))
{
ma = maxn(ma, calc());
return;
}
if (x > n)
return;
dfs(x + 1, nw);
de(x);
s -= a[x].x;
dfs(x + 1, nw + 1);
s += a[x].x;
con(x);
}
int main()
{
int i;
n = re();
m = re();
for (i = 1; i <= n; i++)
a[i].x = re();
sort(a + 1, a + n + 1, comp);
for (i = 1, a[0].suc = 1, a[n + 1].pre = n; i <= n; i++)
{
a[i].pre = i - 1;
a[i].suc = i + 1;
s += a[i].x;
}
dfs(1, 0);
printf("%d", ma);
return 0;
}