题意
终于Alice走出了大魔王的陷阱,可是现在傻傻的她忘了带武器了,这可如何是好???这个时候,一个神秘老人走到她面前答应无偿给她武器,但老人有个条件,需要将所选武器分别放在天平的两端,若天平平衡则可以将天平上的所有武器拿走,还好这个天平锈迹斑斑,只要两端重量相差小于等于m就会保持平衡,Alice傻傻的认为越重的武器越好,求Alice最多能拿走的武器总重量。(不限操作次数)
其中, 。
分析
这题还是比较简单滴。
首先,容易发现,称多次和称一次没有区别,也就是称一次就可以得到最终的答案。假如你称两次,第一次为 ,第二次为
,其中
,那么我们完全可以变成称一次
,使得最终答案不变。所以称多次最后都可以变成称一次。
然后由于最终的限制条件是差值,我们令 表示前
个物品,大的减小的差值为
的最大武器重量。
转移分三种:
- 武器太辣鸡了,不取
- 把武器加入小的那边
- 把武器加入大的那边
然后由于差值可能是负数,我们要给他加上一个大整数。
最终复杂度是 的。
代码如下
#include <bits/stdc++.h>
using namespace std;
int read(){
int x, f = 1;
char ch;
while(ch = getchar(), ch < '0' || ch > '9') if(ch == '-') f = -1;
x = ch - '0';
while(ch = getchar(), ch >= '0' && ch <= '9') x = x * 10 + ch - 48;
return x * f;
}
const int N = 105, maxn = 20000;
int f[N][N * N * 5];
int main(){
int i, j, k, n, m, ans = 0;
n = read(); m = read();
memset(f, 0xc0, sizeof(f));
f[0][maxn] = 0;
for(i = 1; i <= n; i++){
k = read();
for(j = -10000; j <= 10000; j++){
f[i][j + maxn] = max(f[i - 1][j + k + maxn], f[i - 1][j - k + maxn]) + k;
f[i][j + maxn] = max(f[i][j + maxn], f[i - 1][j + maxn]);
}
}
for(i = -m + maxn; i <= m + maxn; i++) ans = max(ans, f[n][i]);
printf("%d", ans);
return 0;
}

京公网安备 11010502036488号