zoukankan      html  css  js  c++  java
  • [HNOI2013]比赛

    Description

    Luogu3230
    BZOJ3139
    其实这道题和[CQOI2009](Luogu3154, BZOJ1306)重了。

    Solution

    搜索。枚举每场比赛的对手。要有两个剪枝:

    1. 可行性剪枝,就是如果每一场都赢也不能达到目标分数就剪掉。
    2. 记忆化,在要枚举下一个人的时候,可以记忆化一下:如果剩下的人的分数的情况已经算过了,就不用再算了,注意这个时候剩下的人是无序的(因为他们之间还没有比赛)。
      当然,为了方便,我们用扣分代替加分,最终分数为(0)即合法。

    Code

    #include <cstdio>
    #include <algorithm>
    #include <iostream>
    #include <map>
    
    typedef unsigned long long ll;
    const int N = 11;
    const ll MOD = 1e9 + 7;
    
    std::map<ll, int> f;
    int a[N], b[N], n;
    
    inline ll hash(int x) {
        ll ans = x-1;
        for (int i = 1; i < x; ++i) ans = ans * 30 + b[i];
        return ans;
    }
    
    ll dfs(int x, int y) { // x和y大战 
        if (a[x] > (x-y) * 3) return 0; // 如果一直都赢也拿不到应有的分就gg 
        if (x == y) {
            if (x == 1) return 1; // 搜到最后一个人结束 
            for (int i = 1; i < x; ++i) b[i] = a[i];
            std::sort(b+1, b+x); // mark : 这里的上界
            ll hs = hash(x);
            return f.count(hs) ? f[hs] : f[hs] = dfs(x-1, 1);
        }
        ll ans = 0;
        if (a[x] >= 3) {
            a[x] -= 3;
            ans += dfs(x, y+1);
            a[x] += 3;
        }
        if (a[x] && a[y]) {
            a[x]--; a[y]--;
            ans += dfs(x, y+1);
            a[x]++; a[y]++;
        }
        if (a[y] >= 3) {
            a[y] -= 3;
            ans += dfs(x, y+1);
            a[y] += 3;
        }
        return ans;
    }
    
    int main() {
        scanf("%d", &n);
        for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);
        std::cout << dfs(n, 1);
        return 0;
    }
    
  • 相关阅读:
    深入理解Http协议
    Http协议详解
    过滤器、监听器、拦截器的区别
    HTTP状态代码集
    理解XML-RPC
    Axis2 解析
    REST SOAP XML-RPC分析比较
    Spring 第一天课程
    Spring 框架学习 有用
    数据库主从复制,读写分离,负载均衡,分表分库的概念 没用
  • 原文地址:https://www.cnblogs.com/wyxwyx/p/hnoi2013match.html
Copyright © 2011-2022 走看看