题解 P1651 【塔】
讲前瞎扯
我dfs过了
发现题解里边好像都是
因为我太菜了,看不懂
正题
首先我们的dfs应该是这个样子的
用
然后我们就可以根据题意进行dfs
void dfs(int now, int h1, int h2) {
if (now == n + 1) {//如果dfs完了,那就退出
if (h1 == h2) ans = max(ans, h1);
return;
}
dfs(now + 1, h1 + a[now], h2);//可以选择把当前的方块
dfs(now + 1, h1, h2 + a[now]);//放到第1或者2堆
dfs(now + 1, h1, h2);//当然也可以不放
}
考虑如何剪枝
所以开数组是不可能了,所以我们选择
map<pair<int, pair<int, int> >, int>ma;
我们在每一次
int s = 0;
s = max(s, dfs(now + 1, h1 + a[now], h2));
s = max(s, dfs(now + 1, h1, h2 + a[now]));
s = max(s, dfs(now + 1, h1, h2));
ma[make_pair(now, make_pair(h1, h1))] = s;
在下一次找到和当前状态相同的时候可以直接返回
if (ma[make_pair(now, make_pair(h1, h1))])
return ma[make_pair(now, make_pair(h1, h1))];
而且上边我们剪的枝可以直接返回
code
#include <bits/stdc++.h>
#define ll long long
#define N 100010
#define M 60
using namespace std;
int n, a[M], ans;
int sum[M];
map<pair<int, pair<int, int> >, int>ma;
int read() {
int s = 0, f = 0; char ch = getchar();
while (!isdigit(ch)) f |= (ch == '-'), ch = getchar();
while (isdigit(ch)) s = s * 10 + (ch ^ 48), ch = getchar();
return f ? -s : s;
}
bool cmp(int a, int b) {
return a > b;
}
int dfs(int now, int h1, int h2) {
if (now == n + 1) {
if (h1 == h2) {
ans = max(ans, h1);
return h1;
}
return -1;
}
if (ma[make_pair(now, make_pair(h1, h1))])
return ma[make_pair(now, make_pair(h1, h1))];
if (h1 + h2 + sum[n] - sum[now - 1] <= ans * 2) return -1;
if (h1 + sum[n] - sum[now - 1] <= ans) return -1;
if (h2 + sum[n] - sum[now - 1] <= ans) return -1;
if (h1 + sum[n] - sum[now - 1] < h2) return -1;
if (h2 + sum[n] - sum[now - 1] < h1) return -1;
int s = 0;
s = max(s, dfs(now + 1, h1 + a[now], h2));
s = max(s, dfs(now + 1, h1, h2 + a[now]));
s = max(s, dfs(now + 1, h1, h2));
ma[make_pair(now, make_pair(h1, h1))] = s;
return s;
}
int main() {
n = read();
for (int i = 1; i <= n; i++) a[i] = read();
sort(a + 1, a + n + 1, cmp);
for (int i = 1; i <= n; i++) sum[i] = sum[i - 1] + a[i];
dfs(1, 0, 0);
if (ans == 0) puts("-1");
else cout << ans;
}
最后放一张惊险又刺激的AC图