可以发现状态数很少。当时和现在状态的数任意组合相加可以有2^n个答案。然后似乎可以用f[i][j]表示当时的状态和现在的状态对应的最优答案。转移的话状压似乎也很方便。
然后我又不会了。。。开始认(mo)真(bai)思(ti)考(jie)。。
为什么题解都是只可意会不可言传啊卧槽。。而且都是一维的好厉害的样子。。
不过题解的第一句话瞬间使我脑洞大开QAQ。。操作数上界是n1+n2,如果有两部分和相同那么操作数可以-2。
这样对应回刚才的dp方程就可以解决了。。
为什么每次思考都差那么一点呢。。还是太弱啦。。
#include<iostream>
#include<cstdio>
using namespace std;
int f[1100][1100];
inline int read()
{
int a=0,f=1; char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();}
while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();}
return a*f;
}
struct node
{
int n;
int x[11];
int sum[1100];
void dfs(int k,int state,int s)
{
if (k==n+1) return;
sum[state<<(n-k)]=s;
dfs(k+1,state*2+1,s+x[k+1]);
dfs(k+1,state*2,s);
}
}A,B;
int main()
{
A.n=read();
for (int i=1;i<=A.n;i++) A.x[i]=read();
B.n=read();
for (int i=1;i<=B.n;i++) B.x[i]=read();
A.dfs(0,0,0); B.dfs(0,0,0);
for (int i=1;i<(1<<A.n);i++)
for (int j=1;j<(1<<B.n);j++)
{
for (int k=1;k<=A.n;k++)
if (i&(1<<(k-1))) f[i][j]=max(f[i][j],f[i-(1<<(k-1))][j]);
for (int k=1;k<=B.n;k++)
if (j&(1<<(k-1))) f[i][j]=max(f[i][j],f[i][j-(1<<(k-1))]);
if (A.sum[i]==B.sum[j]) f[i][j]++;
}
printf("%d",A.n+B.n-2*f[(1<<A.n)-1][(1<<B.n)-1]);
return 0;
}