搜索剪枝
不难的一道题。。然而是省选题。。
枚举每场比赛,枚举编号较小的一队的结果,相应的较大的也可以推出结果
当有某一队剩下比赛全赢也比给定分数低就剪枝
当有某一队当前比分超过给定分数也剪枝
只要你把这俩个剪枝加上,然后提交,你就会神奇的发现
为什么还是狂 T???
我还是
too
naive
,还是被极限数据卡了。。
所以要在加一个,当这个队伍是和最后一支队伍比赛的时候,只要一种答案,如果和分数相差
0,3,1
时就搜剩下的一个相应的状态,相差
2
就剪枝
。。。我以为这个优化毫无卵用,然而TM居然是有用的。。
代码:
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define g getchar()
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
inline ll read(){
ll x=0,f=1;char ch=g;
for(;ch<'0'||ch>'9';ch=g)if(ch=='-')f=-1;
for(;ch>='0'&&ch<='9';ch=g)x=x*10+ch-'0';
return x*f;
}
inline void out(ll x){
int a[25],t=0;
if(x<0)putchar('-'),x=-x;
for(;x;x/=10)a[++t]=x%10;
for(int i=t;i;--i)putchar('0'+a[i]);
if(t==0)putchar('0');
putchar('\n');
}
int n,a[10],f[10],ans;
int opt1[4]={0,3,1,0},opt2[4]={0,0,1,3};
bool pd(){
for(int i=1;i<=n;++i)if(a[i]!=f[i])return 0;
return 1;
}
void dfs(int x,int y){
if(x==n){if(pd())++ans;return;}bool fl=0;
if(y==n){
int t1=f[x],t2=f[y];
if(a[x]-f[x]==2||a[x]-f[x]>3)return;
int opt=a[x]-f[x];
if(opt==1)f[x]=a[x],f[y]++;
else f[x]=a[x],f[y]+=3-opt;
dfs(x+1,x+2);
f[x]=t1,f[y]=t2;
}
else
for(int j=1;j<=3;++j){
f[x]+=opt1[j],f[y]+=opt2[j];
if(f[x]+(n-y)*3<a[x]){f[x]-=opt1[j],f[y]-=opt2[j];continue;}
if(f[x]>a[x]){f[x]-=opt1[j],f[y]-=opt2[j];continue;}
if(f[y]>a[y]){f[x]-=opt1[j],f[y]-=opt2[j];continue;}
if(f[y]+(n-x-1)*3<a[y]){f[x]-=opt1[j],f[y]-=opt2[j];continue;}
dfs(x,y+1);
f[x]-=opt1[j],f[y]-=opt2[j];
}
}
int main(){
n=read();
for(int i=1;i<=n;++i)a[i]=read();
dfs(1,2);
out(ans);
return 0;
}
跑了