[HNOI2013]比赛

题目描述

沫沫非常喜欢看足球赛,但因为沉迷于射箭游戏,错过了最近的一次足球联赛。此次联 赛共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 

但沫沫发现当球队较多时,计算工作量将非常大,所以这个任务就交给你了。请你计算 出可能的比赛过程的数目,由于答案可能很大,你只需要输出答案对10^9+7取模的结果

输入输出格式

输入格式:

第一行是一个正整数N,表示一共有N支球队。 接下来一行N个非负整数,依次表示各队的最后总得分。 输入保证20%的数据满足N<=4,40%的数据满足N<=6,60%的数据满足N<=8,100%的数据 满足3<=N<=10且至少存在一组解。

输出格式:

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

输入输出样例

输入样例#1:
4
4 3 6 4
输出样例#1:
3

说明

20%的数据满足N≤4;

40%的数据满足N≤6;

60%的数据满足N≤8;

100%的数据满足3≤N≤10且至少存在一组解。

转载自ljh2000http://www.cnblogs.com/ljh2000-jump/

考虑直接爆搜的话,就是枚举当前的与之后的每一个比赛的结果是什么,但是复杂度很高。

优化的话,考虑我枚举完一个的得分之后,剩下的状态打乱顺序不会影响最终结果,因为前面的贡献已经计算完毕了。

 

那么我每次从小到大排序,并且把状态压起来,记忆化一下,就可以通过官方数据了,还有诸如鸡兔同笼和得分上限的剪枝也可以加。

 

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<map>
 6 using namespace std;
 7 typedef long long ll;
 8 int Mod=1000000007;
 9 map<ll,int>mp[12];
10 map<ll,bool>use[12];
11 int ans,a[12];
12 int n;
13 ll gethash(int *b)
14 {int i;
15   ll tot=0;
16   for (i=1;i<=n;i++)
17     tot=tot*29+b[i];
18   return tot;
19 }
20 int dfs(int l,int r)
21 {int i;
22   if (a[l]>3*(r-l)) return 0;
23   if (l>=r)
24     {
25       if (a[l]) return 0;
26       if (l==n) return 1;
27       int b[12];
28       for (i=1;i<=n;i++)
29     b[i]=a[i];
30       sort(b+1,b+n+1);
31       ll h=gethash(b);
32       if (use[l+1][h]) return mp[l+1][h];
33       else mp[l+1][h]=dfs(l+1,n);
34       use[l+1][h]=1;
35       return mp[l+1][h];
36     }
37   ll tot=0;
38   if (a[l]>=3)
39     {
40       a[l]-=3;
41       tot+=dfs(l,r-1);
42       tot%=Mod;
43       a[l]+=3;
44     }
45   if (a[l]&&a[r])
46     {
47       a[l]--;a[r]--;
48       tot+=dfs(l,r-1);
49       tot%=Mod;
50       a[l]++;a[r]++;
51     }
52   if (a[r]>=3)
53     {
54       a[r]-=3;
55       tot+=dfs(l,r-1);
56       tot%=Mod;
57       a[r]+=3;
58      }
59   return tot;
60 }
61 int main()
62 {int i;
63   cin>>n;
64   for (i=1;i<=n;i++)
65     scanf("%d",&a[i]);
66   sort(a+1,a+n+1);
67   ans=dfs(1,n);
68   printf("%d",ans%Mod);
69 }

 

posted @ 2017-10-11 18:31  Z-Y-Y-S  阅读(325)  评论(2编辑  收藏  举报