完全没思路,并认为这个问题没有 \(O(n^2w)\) 以下的解法
遂糊了个暴力上去随便优化了一下,然后过了……
正解的话是random_shuffle构造随机数据,然后把第二个班看成负容量做背包
途中舍弃偏离0过远的决策,显然是对的而且没法卡
#include <bits/stdc++.h>
using namespace std;
#define INF 4485090715960753727ll
#define N 100010
#define ll long long
//#define int long long
char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
int ans=0, f=1; char c=getchar();
while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48), c=getchar();
return ans*f;
}
int n, m;
ll w1[N], v1[N], w2[N], v2[N];
namespace force{
ll dp1[1000010], dp2[1000010], sum1, sum2, lim;
void solve() {
for (int i=1; i<=n; ++i) sum1+=w1[i];
for (int i=1; i<=m; ++i) sum2+=w2[i];
lim=min(sum1, sum2);
memset(dp1, -0x3f, sizeof(dp1));
memset(dp2, -0x3f, sizeof(dp2));
dp1[0]=0; dp2[0]=0;
int sum=0;
for (int i=1; i<=n; ++i) {
for (int j=sum; ~j; --j) {
dp1[j+w1[i]]=max(dp1[j+w1[i]], dp1[j]+v1[i]);
}
sum+=w1[i];
}
sum=0;
for (int i=1; i<=m; ++i) {
for (int j=sum; ~j; --j) {
dp2[j+w2[i]]=max(dp2[j+w2[i]], dp2[j]+v2[i]);
}
sum+=w2[i];
}
ll ans=0;
for (int i=1; i<=lim; ++i) ans=max(ans, dp1[i]+dp2[i]);
printf("%lld\n", ans);
exit(0);
}
}
signed main()
{
freopen("game.in", "r", stdin);
freopen("game.out", "w", stdout);
n=read(); m=read();
for (int i=1; i<=n; ++i) w1[i]=read(), v1[i]=read();
for (int i=1; i<=m; ++i) w2[i]=read(), v2[i]=read();
force::solve();
return 0;
}