\(\text{Description}\)

传送门

\(\text{Solution}\)

\(30 \text{pts}\) 就是 \(01\) 背包。

发现我们的瓶颈就是容量要开到 \(1e6\),但其实如果随机一下数据是很难出现这种情况的(我们把正容量和负容量打乱)。因为我们每件物品的容量较小,而且打乱后出现很长一段是正容量,后面是负容量的“山峰”概率很小(最后要保证回到 \(0\) 值)。

所以设定一个可以接受的容量,超出的认为它不行就行了。

好玄学。

\(\text{Code}\)

#include <cstdio>
#define rep(i,_l,_r) for(signed i=(_l),_end=(_r);i<=_end;++i)
#define print(x,y) write(x),putchar(y)

typedef long long ll;

void write(ll x) {
	if(x<0) return (void)(putchar('-'),write(-x));
	if(x>9) write(x/10);
	putchar(x%10^48);
} 

int read() {
	int x=0,f=1; char s;
	while((s=getchar())>'9'||s<'0') if(s=='-') f=-1;
	while(s>='0'&&s<='9') x=(x<<1)+(x<<3)+(s^48),s=getchar();
	return x*f;
}

//C(25,12)=5200300

#include <iostream>
#include <algorithm>
using namespace std;

const int maxn=1005,lim=1e5;
const ll inf=(1ll<<50);

int n,m;
ll f[lim+5],ans;
struct node {
	int w,v;
} s[maxn<<1];

int main() {
	//freopen("game.in","r",stdin); freopen("game.out","w",stdout);
	n=read(),m=read(); srand(20201121);
	rep(i,1,n+m) {
		s[i].w=read(),s[i].v=read();
		if(i>n) s[i].w=-s[i].w;
	}
	random_shuffle(s+1,s+n+m+1);
	rep(i,0,lim) f[i]=-inf;
	f[lim>>1]=0;
	rep(i,1,n+m+1) 
		if(s[i].w>=0) {
			for(int j=lim;j>=s[i].w;--j)
				if(f[j-s[i].w]!=-inf) f[j]=max(f[j],f[j-s[i].w]+s[i].v);
		}
		else {
			rep(j,0,s[i].w+lim)
				if(f[j-s[i].w]!=-inf) f[j]=max(f[j],f[j-s[i].w]+s[i].v);
		}
	print(f[lim>>1],'\n');
	return 0;
}
posted on 2020-11-21 15:45  Oxide  阅读(100)  评论(0编辑  收藏  举报