Description

  沫沫非常喜欢看足球赛,但因为沉迷于射箭游戏,错过了最近的一次足球联赛。此次联 赛共N支球队参加,比赛规则如下: 
    (1) 每两支球队之间踢一场比赛。 (2) 若平局,两支球队各得1分。 
    (3) 否则胜利的球队得3分,败者不得分。 
  尽管非常遗憾没有观赏到精彩的比赛,但沫沫通过新闻知道了每只球队的最后总得分, 然后聪明的她想计算出有多少种可能的比赛过程。 
  譬如有3支球队,每支球队最后均积3分,那么有两种可能的情况:
     可能性1          可能性2 
    球队  A  B  C  得分   球队 A  B  C  得分 
    A        -  3  0    3        A    -  0  3    3 
    B        0  -  3    3        B    3  -   0   3 
    C        3  0  -    3        C    0  3  -    3 
  但沫沫发现当球队较多时,计算工作量将非常大,所以这个任务就交给你了。请你计算 出可能的比赛过程的数目,由于答案可能很大,你只需要输出答案对109+7取模的结果

Input

  第一行是一个正整数N,表示一共有N支球队。 接下来一行N个非负整数,依次表示各队的最后总得分。

  输入保证20%的数据满足N≤4,40%的数据满足N≤6,60%的数据满足N≤8,100%的数据 满足3≤N≤10且至少存在一组解。

Output

  仅包含一个整数,表示答案对10^9+7取模的结果

Sample Input

4
4 3 6 4

Sample Output

3
 
 
题解:记忆化搜索。如果我们直接进行暴力搜索的话,会出现若干重复的情况,那么这个时候我们需要进行判重性剪枝,最直接的方式就是记录已经走过的状态。状态固然是当前每个队伍的得分,因为n<=10,但是即便这么小也不能直接存储,这里我们加一个long long的哈希来存储,开map进行判重。为什么这么暴力的办法是可行的?我们对状态数量进行一下分析就可以大胆使用了。10个队,对于每个队,最多比9场,得27分,那么放入hash函数中,最大为7.77*10^12,在long long范围内,用map存一下就行了。
  搜索的过程也是有讲究的。我们将每支队伍的得分从大到小排序,将得分多的队伍优先进行搜索,每次与当前得分最低的队伍进行匹配,这样可以很快搜完。
 
代码:
-----------------------------------------------------------------------------------------------------

#include <cstdio>
#include <algorithm>
#include <map>
using namespace std;

#define MAXN 15
#define MOD 1000000007

typedef long long ll;

struct Cmp
{
  bool operator () (int a, int b)
  {
    return a > b;
  }
};
Cmp x;

ll a[MAXN];

map <ll, ll> mp;

ll hash(int o)
{
  ll res = o, tmp[MAXN];
  for (int i = 1; i <= o; i++) tmp[i] = a[i];
  sort(tmp + 1, tmp + o + 1, x);
  for (int i = 1; i <= o; i++) res += res * 28 + tmp[i];
  return res;
}

ll DFS(int o, int n)
{
  if (a[n] > 3 * (n - o)) return -1;
  ll res = 0;
  if (o == n)
  {
    if (n == 1) return 1;
    else
    {
      ll h = hash(n - 1);
      if (mp[h]) return mp[h];
      return mp[h] = DFS(1, n - 1);
    }
  }
  if (a[n] >= 3)
  {
    ll tmp = 0;
    a[n] -= 3, tmp = DFS(o + 1, n);
    if (tmp != -1) (res += tmp) %= MOD;
    a[n] += 3;
  }
  if (a[n] && a[o])
  {
    ll tmp = 0;
    a[n]--, a[o]--, tmp = DFS(o + 1, n);
    if (tmp != -1) (res += tmp) %= MOD;
    a[n]++, a[o]++;
  }
  if (a[o] >= 3)
  {
    ll tmp = 0;
    a[o] -= 3, tmp = DFS(o + 1, n);
    if (tmp != -1) (res += tmp) %= MOD;
    a[o] += 3;
  }
  return res ? res : -1;
}

int n;

int main()
{
  freopen("match.in", "r", stdin);
  freopen("match.out", "w", stdout);
  scanf("%d", &n);
  for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
  sort(a + 1, a + n + 1, x);
  printf("%d", DFS(1, n));
  return 0;
}

-----------------------------------------------------------------------------------------------------

[BZOJ3139][HNOI2013] 比赛的更多相关文章

  1. BZOJ1306 [CQOI2009]match循环赛/BZOJ3139 [Hnoi2013]比赛[dfs剪枝+细节题]

    地址 看数据范围很明显的搜索题,暴力dfs是枚举按顺序每一场比赛的胜败情况到底,合法就累计.$O(3^{n*(n-1)/2})$.n到10的时候比较大,考虑剪枝. 本人比较菜所以关键性的剪枝没想出来, ...

  2. [BZOJ3139][HNOI2013]比赛(搜索)

    3139: [Hnoi2013]比赛 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 1439  Solved: 719[Submit][Status] ...

  3. bzoj千题计划294:bzoj3139: [Hnoi2013]比赛

    http://www.lydsy.com/JudgeOnline/problem.php?id=3139 队伍的顺序不会影响结果 将队伍的得分情况作为状态,记忆化搜索 就是先搜索第一只队伍的得分情况, ...

  4. 【BZOJ3139】[HNOI2013]比赛(搜索)

    [BZOJ3139][HNOI2013]比赛(搜索) 题面 BZOJ 洛谷 题解 双倍经验

  5. [HNOI2013]比赛 (用Hash实现记忆化搜索)

    [HNOI2013]比赛 题目描述 沫沫非常喜欢看足球赛,但因为沉迷于射箭游戏,错过了最近的一次足球联赛.此次联 赛共N支球队参加,比赛规则如下: (1) 每两支球队之间踢一场比赛. (2) 若平局, ...

  6. [HNOI2013]比赛 搜索

    [HNOI2013]比赛 搜索. LG传送门 直接暴力有60,考场上写的60,结果挂成40. 考虑在暴力的同时加个记忆化,把剩下的球队数和每支球队的得分情况hash一下,每次搜到还剩\(t\)个队的时 ...

  7. 【题解】HNOI2013比赛

    [题解][P3230 HNOI2013]比赛 将得分的序列化成样例给的那种表格,发现一行和一列是同时确定的.这个表格之前是正方形的,后来长宽都减去一,还是正方形.问题形式是递归的.这就启示我们可以把这 ...

  8. BZOJ3139/BZOJ1306 HNOI2013比赛/CQOI2009循环赛(搜索)

    搜索好难啊. 1.对于每个分数集合记忆化. 2.某人得分超过总分,剪枝. 3.某人之后全赢也无法达到总分,剪枝. 4.每有一场比赛分出胜负总分会多三分,而平局则会多两分.某人的分出胜负场次或平局场次超 ...

  9. 3139:[HNOI2013]比赛 - BZOJ

    题目描述 Description 沫沫非常喜欢看足球赛,但因为沉迷于射箭游戏,错过了最近的一次足球联赛.此次联赛共N只队伍参加,比赛规则如下: (1) 每两支球队之间踢一场比赛. (2) 若平局,两支 ...

随机推荐

  1. Join Attributes

    1. IWorkspaceFactory2 workspaceFactory = new ShapefileWorkspaceFactoryClass() as IWorkspaceFactory2; ...

  2. ThinkPHP3.2.3整合smarty模板(一)

    一.php模板引擎有哪些? 1.1 PHPLIB:一套古老且主流的模板引擎,直接在html中使用PHP变量进行编程: 1.2 Template Blocks:一款轻巧且速度非常快的PHP模板引擎,支持 ...

  3. avl树的操作证明

    以下用大O表示节点,ABC表示三个集合. 仅分析左子树的情况,因为对称,右子树的情况一样. 插入节点前 O /     \ O        A   /    \ B       C 插入节点后: O ...

  4. 浅谈JSON

    JSON的全称是”JavaScript Object Notation”,意思是JavaScript对象表示法,它是一种基于文本,独立于语言的轻量级数据交换格式.XML也是一种数据交换格式,为什么没有 ...

  5. C和指针 第六章 数组名与指针

    指针的算术运算符是指针和数组之间的一种关联,但不是唯一关联: 可以使用数组名作为指向数组第一个元素的指针,但是不可以给数组名赋新的值. //如下声明a int a[10]; //用a作为指向数组第一个 ...

  6. Dynamic range compression

    这段时间终于把手头的东西都搞完了,还剩下一个AEC这个模块,这个模块跟整个系统机制有很大关系,单独的模块意义不大. 另外,刚写完一个分类器,希望能大幅提升音乐流派分类的准确率. 下周正式开搞AEC,把 ...

  7. MATLAB的SAVE命令动态批量保存TXT文件

    1.使用save(): for i=1:6 str=[num2str(i),’.txt’]; m=[1 2; 3 4]; save(str,’m’,’-ascii’);%注意m的单引号,一定记得加上, ...

  8. [转]在MyEclipse中设置struts.xml自动提示功能

    导入标签:<%@ taglib uri="/struts-tags" prefix="s" %> 要想在MyEclipse中实现struts.xml ...

  9. 移动端web开发技巧

    META相关 1. 添加到主屏后的标题(IOS)

  10. spring加载多个配置文件

    首先我们都知道要使用spring,则需要在web.xml中增加如下代码: web.xml: 1:<listener><listener-class>org.springfram ...