n支队伍进行循环赛,胜者得3分,平各得1分,负得0分.现给出各队伍最终分数,求可能符合的胜负情况数.(n<=8)
这个没法状压,只能爆搜了吧。。
主要剪枝有这几个:
某个队伍剩下全赢都达不到分数或已经超过分数剪枝.
当枚举到某个队伍的最后一场比赛时 可通过与结果的差值直接确定这一场情况
如果差3,1,0分就直接确定,差2分或3分以上直接剪枝。
差不多8s刚好卡过去。。
剪枝这个东西 真的就是玄学吧。。
#include<bits/stdc++.h>
#define LL long long
#define clr(x,i) memset(x,i,sizeof(x))
using namespace std;
const int N=10;
int n,a[N],sc[N],st[4]={3,1,0,0},ans=0;
void dfs(int u,int v)
{
if( sc[u]>a[u] || sc[v]>a[v] )return;
if(sc[u]+(n-v+1)*3<a[u])return;
if(u==n){
ans++;return;
}
if(v==n){
int dt=a[u]-sc[u];
if( dt==2 || dt>3 )return;
sc[u]+=dt;sc[v]+=st[dt];
dfs(u+1,u+2);
sc[u]-=dt;sc[v]-=st[dt];
}
else{
sc[u]+=3;dfs(u,v+1);sc[u]-=3;
sc[v]+=3;dfs(u,v+1);sc[v]-=3;
sc[u]+=1;sc[v]+=1;dfs(u,v+1);
sc[u]-=1;sc[v]-=1;
}
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
dfs(1,2);
printf("%d\n",ans);
return 0;
}