洛谷1441 砝码称重

原题链接

挺水的一道题。
\(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;
}

猜你喜欢

转载自www.cnblogs.com/Iowa-Battleship/p/9817412.html