# [BZOJ2064]分裂

[BZOJ2064]分裂

1 6
3 1 2 3

2

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <algorithm>
#include <vector>
using namespace std;

int x = 0, f = 1; char c = getchar();
while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
return x * f;
}

#define maxn 15
#define maxs 3010
#define maxsum 510
#define oo 2147483647

int n1, n2, A1[maxn], A2[maxn];
vector <int> Set[maxsum];
int Sum1[maxs], Sum2[maxs], cbin[maxs];

int f[maxs][maxs];
int dp(int S1, int S2) {
int& ans = f[S1][S2];
if(ans < oo) return ans;
if(!cbin[S1] && !cbin[S2]) return ans = 0;
if(cbin[S1] == 1 && cbin[S2] == 1) return ans = 0;
ans = cbin[S1] + cbin[S2] - 2;
for(int tS = S2 - 1 & S2; tS; tS = tS - 1 & S2)
for(int i = 0; i < Set[Sum2[tS]].size(); i++) if((S1 | Set[Sum2[tS]][i]) == S1)
ans = min(ans, dp(Set[Sum2[tS]][i], tS) + dp(Set[Sum2[tS]][i] ^ S1, tS ^ S2));
return ans;
}

int main() {
n1 = read(); for(int i = 0; i < n1; i++) A1[i] = read();
n2 = read(); for(int i = 0; i < n2; i++) A2[i] = read();

int all = (1 << n1) - 1;
for(int S = 0; S <= all; S++) {
int sum = 0; cbin[S] = 0;
for(int j = 0; j < n1; j++) if(S >> j & 1) sum += A1[j], cbin[S]++;
Set[sum].push_back(S); Sum1[S] = sum;
}
all = (1 << n2) - 1;
for(int S = 0; S <= all; S++) {
cbin[S] = 0;
for(int j = 0; j < n2; j++) if(S >> j & 1) Sum2[S] += A2[j], cbin[S]++;
}
for(int S1 = 0; S1 <= (1 << n1) - 1; S1++)
for(int S2 = 0; S2 <= all; S2++) f[S1][S2] = oo;

printf("%d\n", dp((1 << n1) - 1, all));

return 0;
}


posted @ 2017-06-01 22:09  xjr01  阅读(181)  评论(0编辑  收藏  举报