UOJ Logo zhouzixuan的博客

博客

bzoj 1306: [CQOI2009]match循环赛

2015-08-04 18:02:45 By zhouzixuan
【题目描述】:

【题目解法】:
    哦,忘了给数据范围了,n<=8...显然搜索
    我们考虑剪枝就好
    1.首先只搜一半,另一半是对称的
    2.考虑每个人与最后一个人的胜负情况可以直接算出来
    3.如果当前这个人的得分大于目标得分直接剪掉
    4.(强力剪枝?)我们用f[i]表示某个人用1,3弄出i的最少次数,然后根据当前搜索的情况剪枝
    T了好几发QAQ...
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=9;
const int M=105;
int n,a[N],b[N],f[M],m; long long ans;
inline long long getint()
{
    long long x=0; char c=getchar(); bool flag=false;
    while ((c!='-')&&((c<'0')||(c>'9'))) c=getchar();
    if (c=='-') flag=true,c=getchar();
    while ((c>='0')&&(c<='9')) x=x*10+(long long)(c-'0'),c=getchar();
    if (flag) return -x; else return x;
}
void init()
{
    n=getint(); m=0;
    for (int i=1; i<=n; i++) a[i]=getint(),m=max(m,a[i]);
    memset(f,127,sizeof(f)); f[0]=0;
    for (int i=1; i<=m; i++)
    {
        if (i-1>=0) f[i]=min(f[i],f[i-1]+1);
        if (i-3>=0) f[i]=min(f[i],f[i-3]+1);
    }
}
void dfs(int x,int y)
{
    if (x==n+1) {ans++; return;}
    if (y==n+1) 
    {
        if (a[x]!=b[x]) return;
        dfs(x+1,x+2); return;
    }
    if (f[a[x]-b[x]]>n-y+1) return;
    b[x]+=3; if (b[x]<=a[x]) dfs(x,y+1); b[x]-=3;
    b[x]++; b[y]++; if ((b[x]<=a[x])&&(b[y]<=a[y])) dfs(x,y+1); b[x]--; b[y]--; 
    b[y]+=3; if (b[y]<=a[y]) dfs(x,y+1); b[y]-=3;
}
int main()
{
    init();
    dfs(1,2);
    printf("%lld\n",ans);
    return 0;
}

评论

暂无评论

发表评论

可以用@mike来提到mike这个用户,mike会被高亮显示。如果你真的想打“@”这个字符,请用“@@”。