$ CH5E26\times ~ $ 扑克牌: (计数类DP)



$ solution: $

唉,计数类DP总是这么有套路,就是想不到。

这道题我们首先可以发现牌的花色没有价值,只需要知道每种牌有 $ (0,4] $ 张,牌的面值也不用管,只需要知道总共有 $ (0,13] $ 种牌。然后我们就可以设出状态: $ f[i][j][p][q] $ 表示还剩 $ 1 $ 张有 $ i $ 种牌的,还剩 $ 2 $ 张牌的有 $ j $ 种,还剩 $ 3 $ 张牌的有 $ p $ 种,还剩 $ 4 $ 张牌的有 $ q $ 种,

可能有人会问,怎么想到这种方法的。事实上,这是计数类DP的重点。做题目的时候,我们往往需要去题目里挖掘性质,将题目所给条件进行转化或建模 。然后在数据范围上大胆猜想,更具经验判断。计数类DP,博主目前只会两个套路:

  1. 一个是找基准点(一般用记忆化搜索代替DP)
  2. 然后就是这一种,直接构造法,我们尤其是构造特殊排列的时候。类比这一题,我们可以用轮廓线DP来模拟构造题目所需排列,轮廓线DP里保存的就是构造到某一阶段所剩余(或用了)的元素。就像25语言那道题目。

所以这一道题我们可以枚举放牌的过程,每一次将牌放到排列末尾。当然对于不同的构造方法,轮廓线DP的实现各有千秋。这一道题之所以难,还在于我们如何让转移达到题目要求。题目里唯一一个棘手的限制就是,相邻的牌面值不同。这个情况如果我们只设四维显然不能明确表示出构造到某一阶段的具体状态。所以我们再加一维用来表示当前排列最后一张牌是从还剩四张(或三张,两张,一张)的牌中取出来的。

这个很重要,举个栗子,我现在拥有某种牌4张,我将其中一张放到排列末尾,那么我下一次放牌时如果从牌数为3三的牌中取牌就有可能抽到与我刚刚放的牌一样的牌,这个需要判断一下。(详细可以见代码,代码里转移中类似 (a-(r==2)) 这样的语句就是用来处理这种情况的)

想必大家读到这里应该已经知道如何转移了吧,我们的下一张牌(就是转移),会有四种情况:(要注意我们多加的那一维的影响)

  1. 放到排列末尾的那种牌已经只剩一张了,
  2. 还剩两张
  3. 还剩三张
  4. 还剩四张

然后,计数类DP,往往可以用记忆化搜索来带替DP,比较方便。



$ code: $

#include<iostream>
#include<cstdio>
#include<iomanip>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<ctime>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set> #define ull unsigned long long
#define ll long long
#define db double
#define rg register int using namespace std; int n;
int ch[75],g[5];
ull f[15][15][15][15][5]; inline int qr(){
register char ch; register bool sign=0; rg res=0;
while(!isdigit(ch=getchar()))if(ch=='-')sign=1;
while(isdigit(ch))res=res*10+(ch^48),ch=getchar();
if(sign)return -res; else return res;
} inline ull ask(int a,int b,int c,int d,int r){
ull res=f[a][b][c][d][r]; if(res)return res;
if(a)res=res+ask(a-1,b,c,d,1)*(a-(r==2));
if(b)res=res+ask(a+1,b-1,c,d,2)*2*(b-(r==3));
if(c)res=res+ask(a,b+1,c-1,d,3)*3*(c-(r==4));
if(d)res=res+ask(a,b,c+1,d-1,4)*4*d;
return f[a][b][c][d][r]=res;
} int main(){
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
for(rg i=0;i<=4;++i)f[0][0][0][0][i]=1;
rg t,ff=0; t=qr();
while(t--){
n=qr(); string s;
for(rg i=1;i<=n;++i) cin>>s,++ch[s[0]-49];
for(rg i=1;i<=4;++i) g[i]=0;
for(rg i=0;i<=50;++i) ++g[ch[i]],ch[i]=0;
printf("Case #%d: ",++ff);
cout<<ask(g[1],g[2],g[3],g[4],0)<<endl;;
}
return 0;
}

CH5E26 扑克牌 (计数类DP)的更多相关文章

  1. 动态规划——区间DP,计数类DP,数位统计DP

    本博客部分内容参考:<算法竞赛进阶指南> 一.区间DP 划重点: 以前所学过的线性DP一般从初始状态开始,沿着阶段的扩张向某个方向递推,直至计算出目标状态. 区间DP也属于线性DP的一种, ...

  2. SDOI2010代码拍卖会 (计数类DP)

    P2481 SDOI2010代码拍卖会 $ solution: $ 这道题调了好久好久,久到都要放弃了.洛谷的第五个点是真的强,简简单单一个1,调了快4个小时! 这道题第一眼怎么都是数位DP,奈何数据 ...

  3. $Poj1737\ Connected\ Graph$ 计数类$DP$

    AcWing Description 求$N$个节点的无向连通图有多少个,节点有标号,编号为$1~N$. $1<=N<=50$ Sol 在计数类$DP$中,通常要把一个问题划分成若干个子问 ...

  4. $CF559C\ Gerald\ and\ Fiant\ Chess$ 计数类$DP$

    AcWing Description 有个$H$行$W$列的棋盘,里面有$N$个黑色格子,求一个棋子由左上方格子走到右下方格子且不经过黑色格子的方案数. $1<=H,M<=1e5,1< ...

  5. $CH5302$ 金字塔 区间$DP$/计数类$DP$

    CH Sol f[l][r]表示l到r这段区间对应的金字塔结构种数 发现是f[l][r]是可以由比它小的区间推出来的 比如已知f[l+1][k],f[k+1][r],不难想到f[l][r]+=f[l+ ...

  6. hackerrank【Lego Blocks】:计数类dp

    题目大意: 修一个层数为n,长度为m的墙,每一层可以由长度为1.2.3.4的砖块构成. 每一层都在同一个长度处出现缝隙是方案非法的,问合法的方案数有多少种 思路: 先求出总方案,再减去所有非法的方案数 ...

  7. codeforces 277.5 div2 F:组合计数类dp

    题目大意: 求一个 n*n的 (0,1)矩阵,每行每列都只有两个1 的方案数 且该矩阵的前m行已知 分析: 这个题跟牡丹江区域赛的D题有些类似,都是有关矩阵的行列的覆盖问题 牡丹江D是求概率,这个题是 ...

  8. Codeforces 9D How many trees? 【计数类DP】

    Codeforces 9D How many trees? LINK 题目大意就是给你一个n和一个h 问你有多少个n个节点高度不小于h的二叉树 n和h的范围都很小 感觉有无限可能 考虑一下一个很显然的 ...

  9. Codeforces 28C Bath Queue 【计数类DP】*

    Codeforces 28C Bath Queue LINK 简要题意:有 n 个人等概率随机进入 m 个房间,一个房间可以有多个人,第 i 个房间有 ai 个水龙头,在一个房间的人要去排队装水,他们 ...

随机推荐

  1. Handling Configuration Changes with Fragments

    This post addresses a common question that is frequently asked on StackOverflow: What is the best wa ...

  2. gsensor方向调试【转】

    本文转载自:http://blog.csdn.net/guoguo295/article/details/19545089 版权声明:本文为博主原创文章,未经博主允许不得转载. 以下说明主要是针对gs ...

  3. C#中查找或结束程序域中的主、子进程

    有时候,我们的程序需要启动一些子进程,如嵌入的图形程序. 当启动一个进程后,获得这个进程信息Process,然后其内部在某个时刻启动了一个子进程,这个时候就涉及程序域和进程树的概念.当我们通过非正常操 ...

  4. docker 提高效率 network-bridging 桥接

    安装的时间顺序 bit3 192.168.107.128 wredis 192.168.107.129 wmysql 192.168.107.130 wslave 192.168.107.131 w ...

  5. Vue Router:使用 props 将组件和路由解耦

    在组件中使用 $route 会使之与其对应路由形成高度耦合,从而使组件只能在某些特定的 URL 上使用,限制了其灵活性. 可以使用 props 将组件和路由解耦. 一 路由配置(布尔模式): impo ...

  6. UVa 11582 Colossal Fibonacci Numbers! 紫书

    思路是按紫书上说的来. 参考了:https://blog.csdn.net/qwsin/article/details/51834161  的代码: #include <cstdio> # ...

  7. TypeScript + Webpack 环境搭建

    TypeScript + Webpack 环境搭建步骤 安装Node.js 安装npm 创建一个npm项目 安装typescript,配置ts 安装webpack,配置webpack 初始化一个npm ...

  8. Linq查询语法(1)

    转:http://www.cnblogs.com/ahao214/archive/2013/01/22/2871044.html LINQ的基本格式如下所示:var <变量> = from ...

  9. lambda表达式(1)

    转自:http://www.cnblogs.com/knowledgesea/p/3163725.html 简化了匿名委托的使用,让你让代码更加简洁,优雅.据说它是微软自c#1.0后新增的最重要的功能 ...

  10. “希希敬敬对”团队--‘百度贴吧小爬虫’Alpha版本展示博客

    希希敬敬对的 Alpha阶段测试报告 随笔链接地址 https://www.cnblogs.com/xiaoyoushang/p/10078826.html   Alpha版本发布说明 随笔链接地址 ...