(n) 支队伍比赛,每两支队伍比赛一次。若两支队伍打平,则各得到 (1) 分;否则,胜利的队伍得到 (3) 分,被打败的队伍得到 (0) 分。给出队伍的最终得分,求有多少种可能的分数表。
Solution
大力搜索+剪枝
先枚举 1v2,1v3,...,1vN,再枚举 2v3,2v4,...,2vN,以此类推
为了加速将所有人按照总分从小到大排序
然后利用 hash 记忆化一下
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 10;
const int mod = 11451419198107;
int a[N],n;
map<int,int> h;
int gethash(int i,int j) {
int res = i*17+j;
for(int i=1;i<=n;i++) ((res*=17)+=a[i])%=mod;
return (res+mod)%mod;
}
int dfs(int i,int j) {
if(a[i]<0) return 0;
if(j>n) {
if(a[i]) return 0;
++i, j=i+1;
}
if(h.find(gethash(i,j))!=h.end()) {
return h[gethash(i,j)];
}
int tmp=0;
if(i==n && a[i]==0) ++tmp;
else {
if(a[i]>0 && a[j]>0) {
--a[i]; --a[j];
tmp += dfs(i,j+1);
++a[i]; ++a[j];
}
if(a[i]>2) {
a[i]-=3;
tmp += dfs(i,j+1);
a[i]+=3;
}
if(a[j]>2) {
a[j]-=3;
tmp += dfs(i,j+1);
a[j]+=3;
}
}
h[gethash(i,j)]=tmp;
return tmp;
}
signed main() {
ios::sync_with_stdio(false);
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
sort(a+1,a+n+1);
cout<<dfs(1,2)<<endl;
}