解题报告 『小木棍[数据加强版](深度优先搜索 + 剪枝)』

原题地址

本以为是一道水题,但死活只能拿到27分,总之详情见代码。

本题我用了4类剪枝,剪枝(1,2)没什么好说的,这里说一下剪枝(3,4):

剪枝(3):如果当前原始木棒中“尝试拼入的第一根木棒”的递归分支就返回失败,那么直接判定当前分支失败;

剪枝(4):如果在当前原始木棒中拼入一根木棒后,木棒恰好被拼接完整,并且“接下来拼接剩余木棒”的递归分支返回失败,那么直接判定当前分支失败。

以上两个剪枝分别利用了“空木棒的等效性”和“贪心”。

 

代码实现如下:

#include <bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for (register int i = (a); i <= (b); i++)

const int maxn = 1e2;

int n, cnt, len, tot;
int a[maxn];
bool vis[maxn];

int cmp(int a, int b) {return a > b;}

void origin() {memset(vis, 0, sizeof(vis));}

int read() {
    int x = 0, flag = 0;
    char ch = ' ';
    while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar();
    if (ch == '-') {
        flag = 1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9') {
        x = (x << 1) + (x << 3) + ch - '0';
        ch = getchar();
    }
    return flag ? -x : x;
}

int dfs(int stick, int cab, int last) {
    if (stick > cnt) return 1;
    if (cab == len) return dfs(stick + 1, 0, 1);
    int fail = 0;//剪枝(2),不解释.
    rep(i, last, n) {
        if (!vis[i] && cab + a[i] <= len && a[i] != fail) {
            vis[i] = 1;
            if (dfs(stick, cab + a[i], i + 1)) return 1;
            fail = a[i];
            vis[i] = 0;
            if (!cab || cab + a[i] == len) return 0;//剪枝(3,4).
        }
    }
    return 0;
}

void write(int x) {
    if (x < 0) {
        putchar('-');
        x = -x;
    }
    if (x > 9) write(x / 10);
    putchar(x % 10 + '0');
}

int main() {
    int sum = 0, val = 0;
    n = read();
    rep(i, 1, n) {
        int u = read();
        if (u > 50) continue;
        else {
            a[++tot] = u;
            sum += u;
            val = max(u, val);
        }
    }
    sort(a + 1, a + n + 1, cmp);//剪枝(1),不解释.
    //一开始用的宏定义rep,WA的只有27分.
    for (len = val; len <= sum; len++) {
        if (sum % len) continue;
        cnt = sum / len;
        origin();
        if (dfs(1, 0, 1)) {
            write(len);
               break;
        }
    }
    return 0;
}
View Code
posted @ 2019-05-03 16:35  雲裏霧裏沙  阅读(382)  评论(0编辑  收藏  举报