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

    https://zybuluo.com/ysner/note/1226192

    题面

    (n)个球队,两两比赛,胜得(3)分,平各得(1)分。告知每队最后得分,询问有多少种不同比赛结果。

    • (nleq10)

    解析

    (nleq10)很有深意啊。反正这题不可能状压,那肯定是叫我们打记搜。

    我一开始的想法是把搜索的状态设为各组当时的得分((28^{10})爆不了(long long))。
    然而这样就不能记忆化了,因处理(
    )得分时不知道两个队是否比赛过,强设该状态又炸空间。

    于是还是枚举每场比赛的结果吧。
    当然,可以有剪枝:

    • 将各组最终得分从大到小排序,然后(n对[1,n-1],(n-1)对[1,n-2],...,(2)对[1,1])枚举比赛状态,如果发现前者分数用()不完就(return)
    • (dp[i])记忆化 前面比赛完的人的分数(i)(二十八进制数转十进制)后的方案数。(只有这样设状态才知道哪些队没比赛过)

    还有值得注意的一点,(dp)数组初始值应该设为(-1),这样才能同已经计算过、方案数为(0)的情况区分开来

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<map>
    #define re register
    #define il inline
    #define ll long long
    #define max(a,b) ((a)>(b)?(a):(b))
    #define min(a,b) ((a)<(b)?(a):(b))
    #define fp(i,a,b) for(re int i=a;i<=b;i++)
    #define fq(i,a,b) for(re int i=a;i>=b;i--)
    using namespace std;
    const int mod=1e9+7;
    map<ll,ll>dp;
    ll n,pj,a[20];
    il ll gi()
    {
      re ll x=0,t=1;
      re char ch=getchar();
      while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
      if(ch=='-') t=-1,ch=getchar();
      while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
      return x*t;
    }
    il bool cmp(re ll x,re ll y){return x>y;}
    il ll calc(re int x)
    {
      re ll New=x,d[20];//!!!!
      fp(i,1,x) d[i]=a[i];
        sort(d+1,d+1+x);//!!!!!
      fp(i,1,x) New=New*28+d[i];//!!!!
      return New;
    }
    il ll dfs(re int l,re int r)
    {
        re ll tot=0;
        if(a[r]>3*(r-l)) return -1;
        if(l==r)
            if(r==1) return 1;
            else
            {
                re ll now=calc(r-1);
                if(dp[now]) return dp[now];
                else return dp[now]=dfs(1,r-1);
            }
        if(a[l]>=3)
        {
            a[l]-=3;
            re ll tmp=dfs(l+1,r);if(tmp!=-1) tot+=tmp;if(tot>=mod) tot-=mod;
            a[l]+=3;
        }
        if(a[r]>=3)
        {
            a[r]-=3;
          re ll tmp=dfs(l+1,r);if(tmp!=-1) tot+=tmp;if(tot>=mod) tot-=mod;
            a[r]+=3;
        }
        if(a[l]&&a[r])
        {
            --a[l];--a[r];
            re ll tmp=dfs(l+1,r);if(tmp!=-1) tot+=tmp;if(tot>=mod) tot-=mod;
            ++a[l];++a[r];
        }
        return tot?tot:-1;
    }
    int main()
    {
      n=gi();
      fp(i,1,n) a[i]=gi();
        sort(a+1,a+1+n,cmp);
      printf("%lld
    ",dfs(1,n));
      return 0;
    }
    
  • 相关阅读:
    linux 命令——19 find (转)
    linux 命令——18 locate (转)
    linux 命令——17 whereis(转)
    linux 命令——16 which(转)
    linux 命令——15 tail (转)
    linux 命令——14 head (转)
    Java for LeetCode 038 Count and Say
    Java for LeetCode 037 Sudoku Solver
    Java for LeetCode 036 Valid Sudoku
    Java for LeetCode 035 Search Insert Position
  • 原文地址:https://www.cnblogs.com/yanshannan/p/9367036.html
Copyright © 2011-2022 走看看