zoukankan      html  css  js  c++  java
  • [bzoj3139] 比赛

    Description

    沫沫非常喜欢看足球赛,但因为沉迷于射箭游戏,错过了最近的一次足球联赛。此次联赛共(N)支球队参加,比赛规则如下:

    (1) 每两支球队之间踢一场比赛。

    (2) 若平局,两支球队各得(1)分。

    (3) 否则胜利的球队得(3)分,败者不得分。

    尽管非常遗憾没有观赏到精彩的比赛,但沫沫通过新闻知道了每只球队的最后总得分, 然后聪明的她想计算出有多少种可能的比赛过程。

    譬如有(3)支球队,每支球队最后均积(3)分,那么有两种可能的情况:

    可能性1:

    球队 (A) (B) (C) 得分
    (A) (-) (3) (0) (3)
    (B) (0) (-) (3) (3)
    (C) (3) (0) (-) (3)

    可能性2:

    球队 (A) (B) (C) 得分
    (A) (-) (0) (3) (3)
    (B) (3) (-) (0) (3)
    (C) (0) (3) (-) (3)

    但沫沫发现当球队较多时,计算工作量将非常大,所以这个任务就交给你了。请你计算出可能的比赛过程的数目,由于答案可能很大,你只需要输出答案对(10^9+7)取模的结果

    Input

    第一行是一个正整数(N),表示一共有(N)支球队。 接下来一行(N)个非负整数,依次表示各队的最后总得分。

    输入保证(20\%)的数据满足(Nle 4)(40\%)的数据满足(Nle 6)(60\%)的数据满足(Nle 8)(100\%)的数据满足(3le Nle 10)且至少存在一组解。

    Output

    仅包含一个整数,表示答案对(10^9+7)取模的结果

    Sample Input

    4
    
    4 3 6 4 
    

    Sample Output

    3
    

    Source

    (Hnoi2013)

    题解

    很久很久做的题,先上(Dfs+)减枝,简单的搜索,不必讲解。

    #include<iostream>
    #include<cstdio>
    using namespace std;int n,a[10],now[10],Ans;
    inline void Scanf(int &x)
    {
        x=0;char s=getchar();
        while(s<'0'||s>'9')s=getchar();
        while(s>='0'&&s<='9')x=x*10+s-'0',s=getchar();
    }void Dfs(int t,int T){
        if(now[t]>a[t]||now[T]>a[T])return;
        if(now[t]+(n-T+1)*3<a[t])return;
        if(now[T]+(n-t+1)*3<a[T])return;
        if(t==n){++Ans;return;}
        if(T==n){int YH=a[t]-now[t];
            if(YH==1){++now[t],++now[T];Dfs(t+1,t+2);--now[t],--now[T];}
            if(YH==3){now[t]+=3;Dfs(t+1,t+2);now[t]-=3;}
            if(YH==0){now[T]+=3;Dfs(t+1,t+2);now[T]-=3;}
            return;
        }
        ++now[t],++now[T];Dfs(t,T+1);
        --now[t],--now[T];
        now[t]+=3;Dfs(t,T+1);now[t]-=3;
        now[T]+=3;Dfs(t,T+1);now[T]-=3;
    }int main(){
        int i;Scanf(n);
        for(i=1;i<=n;++i)Scanf(a[i]);
        Dfs(1,2),printf("%d
    ",Ans);
        return 0;
    }
    

    正解是记忆化搜索,从目标状态往前搜索,用(Hash)记录每一种状态,具体见代码:

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    
    typedef long long ll;
    const int N=15,maxn=1000007,inf=1000000007;
    int n,num[N],tmp[N];
    struct node
    {
    	ll id;
    	int ans,next;
    }Hash[maxn+1];
    int hd[maxn+1],cnt;
    
    ll GetHash(int nw)
    {
    	for(int i=1;i<=n;++i) tmp[i]=num[i];
    	sort(tmp+1,tmp+n+1);
    	ll Res=0;
    	for(int i=1;i<=n;++i) Res=Res*27+tmp[i];//10个球队,最高比分为27
    	return Res*27+nw;//由于当状态相同时未比赛的队伍数必须相同,所以还要把nw也算入Hash值
    }
    
    int Find(ll id)//差询
    {
    	int Id=id%maxn;
    	for(int i=hd[Id];i;i=Hash[i].next)
    		if(Hash[i].id==id) return Hash[i].ans;
    	return -1;
    }
    
    int Insert(ll id,int ans)//将新计算的值记录于Hash表
    {
    	int YH=id%maxn;
    	++cnt,Hash[cnt]=(node){id,ans,hd[YH]},hd[YH]=cnt;
    	return ans;
    }
    
    int Dfs(int nw,int nt)//nw表示当前枚举的球队,nt表示与之比赛的球队
    {
    	if(nw==n)
    	{
    		if(num[n]) return 0;
    		return 1;//初始值为0
    	}
    	if(nt>n)
    	{
    		if(num[nw]) return 0;
    		ll id=GetHash(nw);//计算Hash值
    		int YH=Find(id);//在Hash表查询次数
    		if(YH!=-1) return YH;//已计算
    		return Insert(id,Dfs(nw+1,nw+2));//记录
    	}
    	int Res=0;
    	if(num[nw]>=3)//与之比赛的球队赢
    	{
    		num[nw]-=3,
    		Res=(Res+Dfs(nw,nt+1))%inf,
    		num[nw]+=3;
    	}
    	if(num[nw]>=1&&num[nt]>=1)//平局
    	{
    		--num[nw],--num[nt],
    		Res=(Res+Dfs(nw,nt+1))%inf,
    		++num[nw],++num[nt];
    	}
    	if(num[nt]>=3)//当前枚举的球队赢
    	{
    		num[nt]-=3,
    		Res=(Res+Dfs(nw,nt+1))%inf,
    		num[nt]+=3;
    	}
    	return Res;
    }
    
    int main()
    {
    	scanf("%d",&n);
    	for(int i=1;i<=n;++i) scanf("%d",&num[i]);
    	sort(num+1,num+n+1);//可以去掉
    	int Ans=Dfs(1,2);
    	printf("%d
    ",Ans);
    	return 0;
    }
    

    本文作者:OItby @ https://www.cnblogs.com/hihocoder/

    未经允许,请勿转载。

  • 相关阅读:
    ChsDet is a Charset Detector (检测字符编码)
    Microsoft Fakes进行单元测试
    区域及分离、Js压缩、css、jquery扩展
    服务端软件的服务品质
    警告: [SetPropertiesRule]{Server/Service/Engine/Host/Context}
    开发之技能
    分布式
    工具集
    Visual Studio Code
    Autofac 入门
  • 原文地址:https://www.cnblogs.com/hihocoder/p/11394926.html
Copyright © 2011-2022 走看看