BZOJ3139 HNOI2013比赛 (搜索)

传送门
拿到这道题我开始想了想有没有什么递推关系?然后想了想状压DP?
均无果……
开始写搜索,练习赛是只拿到了70分(暴力+剪枝),对每一场比赛搜索……

看题解才发现是记忆化搜索。在搜索的时候可以将当前状态Hash下来。应为每个队最多只打9场比赛,所以最大得分27分,只有10个队伍,用28进制int64能装下。
而且不应该一场比赛一场比赛的搜,这样就不好利用之前的状态(因为这道题里每个人是等价的,所以K个人的方案数可以由对应的K-1个人的方案数和这个人的胜负情况求得)

下面给出上述的两个代码
70分

#include<cstdio>
#include<algorithm>
using namespace std;
char n, w[15], a[105], b[105], cnt, sum, q[105], c[105];
int ans;
inline bool cmp(char x, char y) {
    return w[a[x]] + w[b[x]] < w[a[y]] + w[b[y]];
}
void dfs(char u, char tot) {
    if(tot + (cnt - u + 1)*2 > sum || tot + (cnt - u + 1)*3 < sum) return;
    if(u == cnt+1) { ++ ans; return; }
    char p = q[u]; -- c[a[p]]; -- c[b[p]];
    if(w[a[p]] >= 3 && c[b[p]]*3 >= w[b[p]]) {
        w[a[p]] -= 3;
        dfs(u+1, tot + 3);
        w[a[p]] += 3;
    }
    if(w[b[p]] >= 3 && c[a[p]]*3 >= w[a[p]]) {
        w[b[p]] -= 3;
        dfs(u+1, tot + 3);
        w[b[p]] += 3;
    }
    if(w[a[p]] && w[b[p]] && c[b[p]]*3+1 >= w[b[p]] && c[a[p]]*3+1 >= w[a[p]]) {
        w[a[p]] --; w[b[p]] --;
        dfs(u+1, tot + 2);
        w[a[p]] ++; w[b[p]] ++;
    }++ c[a[p]]; ++ c[b[p]];
}
int main() {
    scanf("%d", &n);
    for(char i = 0; i < n; ++ i) {
        scanf("%d", w + i);
        sum += w[i];
    }
    for(char i = 0; i < n; ++ i)
        for(char j = i+1; j < n; ++ j) {
            ++ cnt; a[cnt] = i; b[cnt] = j;
            q[cnt] = cnt; ++ c[i]; ++ c[j];
            if(a[cnt] < b[cnt]) swap(a[cnt], b[cnt]);
        }
    sort(q + 1, q + 1 + cnt, cmp);
    dfs(1, 0);
    printf("%d\n", ans);
    return 0;
}

AC代码:

/************************************************************** Problem: 3139 User: geng4512 Language: C++ Result: Accepted Time:592 ms Memory:1736 kb ****************************************************************/

#include<cstdio>
#include<map>
#include<algorithm>
using namespace std;
typedef unsigned long long LL;
int n;
map<LL, int> mp;
inline bool cmp(int a, int b) {
    return a > b;
}
struct Sta {
    int a[12];
    inline LL Hash() {
        LL tmp = 0;
        for(int i = 0; i <= a[0]; ++ i)
            tmp = tmp * 28 + a[i];
        return tmp;
    }
}a;
int dfs(int st, Sta s) {
    int t = s.a[0];
    if(t == 1) return 0;
    if(s.a[t] > st*3) return 0;
    if(st < 1) {
        sort(s.a+1, s.a+t+1, cmp);
        -- s.a[0]; LL p = s.Hash();
        if(mp.count(p)) return mp[p];
        return mp[p] = dfs(s.a[0]-1, s);
    }
    int res = 0;
    if(s.a[t] >= 3) {
        s.a[t] -= 3;
        res += dfs(st-1, s);
        s.a[t] += 3;
    }
    if(s.a[t] >= 1 && s.a[st] >= 1) {
        -- s.a[t]; -- s.a[st];
        res += dfs(st-1, s);
        ++ s.a[t]; ++ s.a[st];
    }
    if(s.a[st] >= 3) {
        s.a[st] -= 3;
        res += dfs(st-1, s);
        s.a[st] += 3;
    }
    if(st == t-1) return mp[s.Hash()] = res;
    return res;
}
int main() {
    scanf("%d", &n);
    for(int i = 1; i <= n; ++ i)
        scanf("%d", a.a+i);
    sort(a.a+1, a.a+n+1, cmp);
    a.a[0] = n;
    mp[28] = 1;
    int ans = dfs(n-1, a);
    printf("%d\n", ans);
    return 0;
}


你可能感兴趣的:(搜索)