# 题目分析：

$f[i][j]$表示数组$1$$i$状态和数组$2$$j$状态存在的相同面积的子集数量，于是就可以枚举子集进行$dp$求出$f[(1 << n1) - 1][(1 << n2) - 1]$，最后答案即为$n1 + n2 - 2 * f[(1 << n1) - 1][(1 << n2) - 1]$

# code

580ms

#include<bits/stdc++.h>
using namespace std;

const int N = 15;
int n1, n2, a1[N], a2[N], sum1[1100], sum2[1100], f[1100][1100];

inline int count(int x){
int ret = 0;
while(x) ret++, x = x & (x - 1);
return ret;
}

struct ioSys{
int i = 0, f = 1; char ch = getchar();
for(; (ch < '0' || ch > '9') && ch != '-'; ch = getchar());
if(ch == '-') f = -1, ch = getchar();
for(; ch >= '0' && ch <= '9'; ch = getchar())
i = (i << 3) + (i << 1) + (ch - '0');
return i * f;
}

inline void wr(int x){
if(x < 0) putchar('-'), x = -x;
if(x > 9) wr(x / 10);
putchar(x % 10 + '0');
}
inline void operator >> (int &x){
}
inline void operator << (int x){
wr(x);
}
}IO;

int main(){
freopen("h.in", "r", stdin);
IO >> n1;
for(int i = 1; i <= n1; i++) IO >> a1[i];
for(int i = 0; i <= (1 << n1) - 1; i++){
for(int j = 1; j <= n1; j++)
if((1 << (j - 1)) & i) sum1[i] += a1[j];
// cout<<sum1[i]<<" ";
}
// cout<<endl;
IO >> n2;
for(int i = 1; i <= n2; i++) IO >> a2[i];
for(int i = 0; i <= (1 << n2) - 1; i++){
for(int j = 1; j <= n2; j++)
if((1 << (j - 1)) & i) sum2[i] += a2[j];
// cout<<sum2[i]<<" ";
}
// cout<<endl;
//---------------------------------------
for(int i = 0; i <= (1 << n1) - 1; i++)
for(int j = 0; j <= (1 << n2) - 1; j++){
if(sum1[i] == sum2[j]){
f[i][j]++;
for(int k = i & (i - 1); k; k = i & (k - 1))
for(int l = j & (j - 1); l; l = j & (l - 1)){
// if(sum1[k] == sum2[l]) f[k][l]++;
f[i][j] = max(f[i][j], f[i - k][j - l] + f[k][l]);
}
}
}
// cout<<f[(1 << n1) - 1][(1 << n2) - 1]<<endl;
IO << n1 + n2 - 2 * f[(1 << n1) - 1][(1 << n2) - 1];
}


posted @ 2017-10-12 20:23  CzYoL  阅读(120)  评论(0编辑  收藏  举报