P2392 kkksc03考前临时抱佛脚
昨天晚上看了题目没思路。 早上上课回来之后想着就直接根据题目搞一个左脑一个右脑,然后两边分别加时间取最大暴搜,结果T了九个,这是代码。
#include <iostream>
using namespace std;
int tAns, ans;
int s[5], array[30];
bool is_use[30];
void preprocessing() {
for (int i = 1; i <= 4; i++) {
cin >> s[i];
}
}
void dfs(int step, int left, int right, int n) {
int ans = max (left, right);
if (ans >= tAns) {
return;
}
if (step == n) {
tAns = min(ans, tAns);
}
for (int i = 1; i <= n; i++) {
if (!is_use[i]) {
is_use[i] = true;
dfs(step + 1, left + array[i], right, n);
dfs(step + 1, left, right + array[i], n);
is_use[i] = false;
}
}
}
void solve() {
for (int i = 1; i <= 4; i++) {
tAns = 0x7fffffff;
for (int j = 1; j <= s[i]; j++) {
cin >> array[j];
}
dfs(0, 0, 0, s[i]);
ans += tAns;
}
cout << ans;
}
int main() {
preprocessing();
solve();
return 0;
}
尝试了各种剪枝,还是过不了一点。
最后发现问题是这个循环。
for (int i = 1; i <= n; i++) {
if (!is_use[i]) {
is_use[i] = true;
dfs(step + 1, left + array[i], right, n);
dfs(step + 1, left, right + array[i], n);
is_use[i] = false;
}
}
实际上无脑公式化套用了前面几道搜索题的做法,类似套模板,没有真的理解这道题的本质。
这道题left和right两个分别加上时间的做法任务就是试完n个,而不需要每一次都从1到n试。
具体的,对于每一个状态,只需从left和right中选择一个进入。
对于这样一个问题,只要按顺序一个个试下去,每个都试left和right即可。
所以这段代码把循环去了就AC了。
#include <iostream>
using namespace std;
int tAns, ans;
int s[5], array[30];
void preprocessing() {
for (int i = 1; i <= 4; i++) {
cin >> s[i];
}
}
void dfs(int step, int left, int right, int n) {
int ans = max (left, right);
if (ans >= tAns) {
return;
}
if (step == n) {
tAns = ans;
return;
}
dfs(step + 1, left + array[step + 1], right, n);
dfs(step + 1, left, right + array[step + 1], n);
return;
}
void solve() {
for (int i = 1; i <= 4; i++) {
for (int j = 1; j <= s[i]; j++) {
cin >> array[j];
}
tAns = 0x7fffffff;
dfs(0, 0, 0, s[i]);
ans += tAns;
}
cout << ans;
}
int main() {
preprocessing();
solve();
return 0;
}