BZOJ 1306: [CQOI2009]match循环赛

来源:互联网 发布:干数据维护工资多少 编辑:程序博客网 时间:2024/05/29 14:35

搜索剪枝
不难的一道题。。然而是省选题。。
枚举每场比赛,枚举编号较小的一队的结果,相应的较大的也可以推出结果
当有某一队剩下比赛全赢也比给定分数低就剪枝
当有某一队当前比分超过给定分数也剪枝
只要你把这俩个剪枝加上,然后提交,你就会神奇的发现


为什么还是狂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 0x3f3f3f3fusing 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;}

跑了8000+ms9000???)我真是菜的可以。。

0 0