洛谷1441 砝碼稱重
阿新 • • 發佈:2018-11-10
原題連結
挺水的一道題。
\(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; }