# 题解&分析

$dp[i][j] = max( dp[i*2][k] + dp[i*2+1][j-k] )$

# 代码：

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
using namespace std;
const int MAXN = 1026;
int n, m;
int w[MAXN][MAXN], f[MAXN][MAXN];
int dp[MAXN][MAXN];
bool vis[MAXN];
void dfs(int x, int now) {
for (int i = 0; i <= ( 1 << now ); i++) dp[x][i] = 0;
if (!now) {
for (int i = 1; i <= n - 1; i++) {
if (vis[i])
dp[x][1] += w[x][i];
else
dp[x][0] += f[x][i];
}
return;
}
vis[now] = 0;
dfs(x * 2, now - 1);
dfs(x * 2 + 1, now - 1);
for (int j = 0; j <= ( 1 << now ); j++) {
for (int k = 0; k <= j; k++) dp[x][j] = max(dp[x][j], dp[x * 2][k] + dp[x * 2 + 1][j - k]);
}
vis[now] = 1;
dfs(x * 2, now - 1);
dfs(x * 2 + 1, now - 1);
for (int j = 0; j <= ( 1 << now ); j++) {
for (int k = 0; k <= j; k++) dp[x][j] = max(dp[x][j], dp[x * 2][k] + dp[x * 2 + 1][j - k]);
}
}
int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= (1 << (n - 1)); i++) {
for (int j = 1; j < n; j++) scanf("%d", &w[(1 << (n - 1)) + i - 1][j]);
}
for (int i = 1; i <= (1 << (n - 1)); i++) {
for (int j = 1; j < n; j++) scanf("%d", &f[(1 << (n - 1)) + i - 1][j]);
}
dfs(1, n - 1);
for (int i = 0; i <= m; i++) dp[1][1] = max(dp[1][1], dp[1][i]);
printf("%d\n", dp[1][1]);
}


03-30 77
10-19 80

03-30 139
01-09 17
09-09 188
08-21 7248
01-18 268
01-01 6万+
11-28 2148
08-26 736