zoukankan      html  css  js  c++  java
  • 【解题报告】编程之美初赛二 扑克牌

    原题地址:http://hihocoder.com/contest/msbop2015round2b/problem/1

    本博客讲的是大数据的解法。
    这题是使用动态规划解,定义状态:

    struct node
    {
            int z,a[4];
    }
    其中a[i]表示当前状态下数量是i+1张的点数的牌的个数。
    如:样例中 6 AC AD AS JC JD KD
    A有3张,J有2张,K有一张,则a[0]=1,a[1]=1,a[2]=1
    若是 6 AC AD AS JC JD JS 则a[2]=2,其他是0。

    依次取每一张牌组成序列,其中z表示前一张牌的点数现在有z+1张。(z=-1时表示现在是0张)
    如对于6 AC AD AS JC JD JS这个例子,初始状态为{z=-1,a=[0,0,2,0]}
    则第一张牌可以是6张的任意一张,取任意一张所造成的状态都是{z=2,a=[0,1,1,0]}

    对于任意状态{z,a0,a1,a2,a3}可以转化为4种状态,分别是:

    {-1,a0-1,a1,a2,a3}:这个状态实际上是a0种选择(如果z不是0的话),因此总和要将这个状态的结果乘a0。如果z是0,则只有a0-1种选择,因为不能选择和前一张牌一样的点数。
    {0,a0+1,a1-1,a2,a3}:这个状态是a1*2种选择,因为每种点数的牌有两张。如果z是1,则是(a1-1)*2种选择。
    {1,a0,a1+1,a2-1,a3}
    {2,a0,a1,a2+1,a3-1}

    所以状态转移方程为:

    f{z,a0,a1,a2,a3}=f{-1,a0-1,a1,a2,a3}    *(z==0?a0:a0-1)*1
                            +f{0,a0+1,a1-1,a2,a3}*(z==1?a1:a1-1)*2
                            +f{1,a0,a1+1,a2-1,a3}*(z==2?a2:a2-1)*3
                            +f{2,a0,a1,a2+1,a3-1}*(z==3?a3:a3-1)*4

    代码如下:(记忆化搜索写法)

    #include<stdio.h>
    #include<iostream>
    #include<string.h>
    #include<map>
    using namespace std;
    typedef unsigned long long ll;
    struct node
    {
        int z,a[4];
        bool operator<(const node &no) const
        {
            if(z!=no.z) return z<no.z;
            for(int i=0;i<4;i++)
                if(a[i]!=no.a[i]) return a[i]<no.a[i];
        }
    };
    map<node,ll> M;
    int num[100],n;
    ll dfs(node no)
    {
        if(M.count(no))
        {
            return M[no];
        }
        if(no.a[0]==0&&no.a[1]==0&&no.a[2]==0&&no.a[3]==0)
        {
            return 1;
        }
        ll ans=0;
        for(int i=0;i<4;i++)
        {
            if(no.a[i]!=0)
            {
                node no2;
                no2.z=i-1;
                no2.a[0]=no.a[0];
                no2.a[1]=no.a[1];
                no2.a[2]=no.a[2];
                no2.a[3]=no.a[3];
                no2.a[i]--;
                if(i!=0) no2.a[i-1]++;
                if(i==no.z)
                {
                    ans+=(no.a[i]-1)*(i+1)*dfs(no2);
                }
                else
                {
                    ans+=(no.a[i])*(i+1)*dfs(no2);
                }
            }
        }
        return M[no]=ans;
    }
    int main()
    {
        int t,i,cas=1;
        char s[5];
        scanf("%d",&t);
        while(t--)
        {
            memset(num,0,sizeof(num));
            scanf("%d",&n);
            for(i=0;i<n;++i)
            {
                scanf("%s",s);
                if(s[0]>='2'&&s[0]<='9')
                {
                    num[s[0]-'0']++;
                }
                else
                {
                    if(s[0]=='A')
                    {
                        num[1]++;
                    }
                    else if(s[0]=='T')
                    {
                        num[10]++;
                    }
                    else if(s[0]=='J')
                    {
                        num[11]++;
                    }
                    else if(s[0]=='Q')
                    {
                        num[12]++;
                    }
                    else if(s[0]=='K')
                    {
                        num[13]++;
                    }
                }
            }
            node no;
            no.z=-1;
            memset(no.a,0,sizeof(no.a));
            for(i=1;i<=13;i++)
            {
                if(num[i]!=0) no.a[num[i]-1]++;
            }
            printf("Case #%d: %llu
    ",cas++,dfs(no));
        }
        return 0;
    }
    

      

  • 相关阅读:
    分分钟提升命令行模式下密码输入逼格
    MySQL server has gone away 的两个最常见的可能性
    第一次遇到刷新缓冲区延时
    Mac上安装mysqlclient的报错
    python3 --- locale命名空间让程序更加安全了
    doctest --- 一个改善python代码质量的工具
    MySQL优化器 --- index_merge
    机智的MySQL优化器 --- is null
    Centos-7.x 下子网掩码的配置
    JS组件系列——BootstrapTable+KnockoutJS实现增删改查解决方案(三):两个Viewmodel搞定增删改查
  • 原文地址:https://www.cnblogs.com/syiml/p/4480372.html
Copyright © 2011-2022 走看看