题目链接:点击打开链接
思路:
类似背包, 很容易想到用d[i][j][s]表示前i个数字选了j个和为s的情况是否存在, 复杂度略高, 考虑到这是个布尔类型, 可以用bitset转移, 复杂度/6, 这样就可以过掉全部数据了。
细节参见代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include <stack>
#include <ctime>
#include <bitset>
#include <cstdlib>
#include <cmath>
#include <set>
#include <list>
#include <deque>
#include <map>
#include <queue>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int maxn = 255;
int T,n,m,k,a,b,val[maxn],l[75010],r[75010];
bitset<75010> d[2][maxn];
int main() {
scanf("%d%d%d%d", &n, &k, &a, &b);
int sum = 0;
for(int i = 1; i <= n; i++) {
scanf("%d", &val[i]);
sum += val[i];
}
int u = 1;
d[u][0][0] = 1;
for(int i = 1; i <= n; i++) {
u ^= 1;
for(int j = 0; j <= k; j++) {
d[u][j].reset();
d[u][j] = d[u^1][j];
if(j > 0) d[u][j] |= (d[u^1][j-1]<<val[i]);
}
}
int ans = 0,pos = -INF;
int len = max(sum, b);
for(int s = 0; s <= len; s++) {
if(d[u][k][s]) {
l[s] = s;
pos = s;
}
else l[s] = pos;
}
pos = INF;
for(int s = len; s >= 0; s--) {
if(d[u][k][s]) {
r[s] = s;
pos = s;
}
else r[s] = pos;
}
for(int s = a; s <= b; s++) {
int cur;
if(l[s] == -INF) cur = abs(s - r[s]);
else if(r[s] == INF) cur = abs(l[s] - s);
else cur = min(abs(s - l[s]), abs(r[s] - s));
ans = max(ans, cur);
}
printf("%d\n", ans);
return 0;
}