Pro
https://acm.hdu.edu.cn/showproblem.php?pid=7140
Sol
f i , j , k f_{i,j,k} fi,j,k表示前i个物品,异或和为j,体积为k的方案是否存在
则状态转移方程为 f i , j , k = f i − 1 , j , k ∣ f i − 1 , j ⊕ v , k − w f_{i,j,k}=f_{i-1,j,k}|f_{i-1,j\oplus v,k-w} fi,j,k=fi−1,j,k∣fi−1,j⊕v,k−w
使用滚动数组将第一维滚掉,用bitset优化掉最后一维
关于下面代码中的g[j]=f[j]<<x
说明:此处使用左移可以理解为,当第
i
i
i次移动
v
i
v_i
vi时,最终总的移动为
∑
i
=
1
n
v
i
x
i
,
x
i
=
0
/
1
\sum_{i=1}^n v_ix_i,x_i={0/1}
∑i=1nvixi,xi=0/1。如果总的移动次数为
m
m
m,也就是bitset的第
m
m
m位为1,就说明可以恰好装满整个背包。
Code
//By cls1277
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
#define Fo(i,a,b) for(LL i=(a); i<=(b); i++)
#define Ro(i,b,a) for(LL i=(b); i>=(a); i--)
#define Eo(i,x,_) for(LL i=head[x]; i; i=_[i].next)
#define Ms(a,b) memset((a),(b),sizeof(a))
#define endl '\n'
const LL maxn = 1030;
bitset<maxn> f[maxn], g[maxn];
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
#ifdef DEBUG
freopen("data.txt","r",stdin);
#endif
LL t; cin>>t;
while(t--) {
LL n, m; cin>>n>>m;
Fo(i,0,1023) f[i].reset();
f[0][0] = 1;
Fo(i,1,n) {
LL x, y; cin>>x>>y;
Fo(j,0,1023) g[j]=f[j]<<x;
Fo(j,0,1023) f[j]|=g[j^y];
}
LL ans = -1;
Ro(i,1023,0) {
if(f[i][m]) {
ans = i;
break;
}
}
cout<<ans<<endl;
}
return 0;
}