Reference: https://www.cnblogs.com/liu-runda/p/6019426.html
Amazing
Obviously, the most intuitive transfer is to combine all and split them one by one, which is n + m times, and then set f [I] [J] to take I separately, j state can be at most the same size of the number of sets, enumeration of New plus block transfer, the answer is n + m-2 * f [(1 <n)-1] [(1 <m) -1]
The reason is that the two shards with the same volume can be transferred by themselves, and they do not need to be merged with other shards.
#include<iostream>#include<cstdio>using namespace std;const int N=2005;int n,m,ln,lm,a[N],b[N],sa[N],sb[N],f[N][N];int main(){ scanf("%d",&n); for(int i=0;i<n;i++) { scanf("%d",&a[i]); sa[1<<i]=a[i]; } scanf("%d",&m); for(int i=0;i<m;i++) { scanf("%d",&b[i]); sb[1<<i]=b[i]; } ln=1<<n,lm=1<<m; for(int i=1;i<ln;i++) sa[i]=sa[i^(i&(-i))]+sa[i&(-i)]; for(int i=1;i<lm;i++) sb[i]=sb[i^(i&(-i))]+sb[i&(-i)]; for(int i=1;i<ln;i++) for(int j=1;j<lm;j++) { for(int k=0;k<n;k++) if(i&(1<<k)) f[i][j]=max(f[i][j],f[i^(1<<k)][j]); for(int k=0;k<m;k++) if(j&(1<<k)) f[i][j]=max(f[i][j],f[i][j^(1<<k)]); if(sa[i]==sb[j]) f[i][j]++; } printf("%d\n",n+m-2*f[ln-1][lm-1]); return 0;}
Bzoj 2064: Split [Pressure DP]