CH5E26 扑克牌

题意

5E26 扑克牌 0x5E「动态规划」练习

描述

一副不含王的扑克牌由52张牌组成,由红桃、黑桃、梅花、方块4组牌组成,每组13张不同的面值。现在给定52

张牌中的若干张,请计算将它们排成一列,相邻的牌面值不同的方案数。

牌的表示方法为XY,其中X为面值,为2、3、4、5、6、7、8、9、T、J、Q、K、A中的一个。Y为花色,为S、

H、D、C中的一个。如2S、2H、TD等。

输入格式

第一行为一个整数T,为数据组数。

之后每组数据占一行。这一行首先包含一个整数N,表示给定的牌的张数,接下来N个由空格分隔的字符串,每个字符串长度为2,表示一张牌。每组数据中的扑克牌各不相同。

输出格式

对于每组数据输出一行,形如"Case #X: Y"。X为数据组数,从1开始。Y为可能的方案数,由于答案可能很大,

请输出模2^64之后的值。

样例输入

5
1 TC
2 TC TS
5 2C AD AC JC JH
4 AC KC QC JC
6 AC AD AS JC JD KD

样例输出

Case #1: 1
Case #2: 0
Case #3: 48
Case #4: 24
Case #5: 120

数据范围与约定

  • 1 ≤ T ≤ 20000,1 ≤ N ≤ 52

分析

由于相同种类的牌的牌数只有1-4,而方案数容斥跟牌数相关,所以考虑以牌数建立状态。设\(F[a][b][c][d]\),表示1张的有a种,2张的有b种,3张的有c种,4张的有d种。

考虑如何容斥。首先如果放的是1张牌的,就只有a种方案。当牌数大于1时,用一个决策后的状态计算,要减去它转移到的不合法的状态。

代码

#include<bits/stdc++.h>
#define rg register
#define il inline
#define co const
template<class T>il T read(){
    rg T data=0,w=1;rg char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') w=-1;ch=getchar();}
    while(isdigit(ch)) data=data*10+ch-'0',ch=getchar();
    return data*w;
}
template<class T>il T read(rg T&x) {return x=read<T>();}
typedef unsigned long long ull;
co int N=20;
int n,num[N],c[N];
ull f[N][N][N][N];
char s[N];
ull dp(int a,int b,int c,int d){
    if(f[a][b][c][d]!=-1LLU) return f[a][b][c][d];
    ull ans=0;
    if(a>0) ans+=(ull)a*dp(a-1,b,c,d);
    if(b>0) ans+=(ull)b*2*(dp(a+1,b-1,c,d)-dp(a,b-1,c,d));
    if(c>0) ans+=(ull)c*3*(dp(a,b+1,c-1,d)-2*(dp(a+1,b,c-1,d)-dp(a,b,c-1,d)));
    if(d>0) ans+=(ull)d*4*(dp(a,b,c+1,d-1)-3*(dp(a,b+1,c,d-1)-2*(dp(a+1,b,c,d-1)-dp(a,b,c,d-1))));
    return f[a][b][c][d]=ans;
}
int work(char c){
    switch (c){
        case 'T': return 10;
        case 'J': return 11;
        case 'Q': return 12;
        case 'K': return 13;
        case 'A': return 1;
        default: return c-'0';
    }
}
void Poker(int t){
    read(n);
    memset(num,0,sizeof num);
    memset(c,0,sizeof c);
    for(int i=1;i<=n;++i)
        scanf("%s",s+1),++num[work(s[1])];
    for(int i=1;i<=13;++i) ++c[num[i]];
    printf("Case #%d: %llu\n",t,dp(c[1],c[2],c[3],c[4]));
}
int main(){
    memset(f,-1,sizeof f);
    f[0][0][0][0]=1;
    for(int T=read<int>(),t=1;t<=T;++t) Poker(t);
    return 0;
}

原文地址:https://www.cnblogs.com/autoint/p/10803388.html

时间: 2024-10-10 17:37:54

CH5E26 扑克牌的相关文章

CH5E26 扑克牌 (计数类DP)

\(CH~5E26~*~\)扑克牌: (计数类DP) \(solution:\) 唉,计数类DP总是这么有套路,就是想不到. 这道题我们首先可以发现牌的花色没有价值,只需要知道每种牌有 \((0,4]\) 张,牌的面值也不用管,只需要知道总共有 \((0,13]\) 种牌.然后我们就可以设出状态: \(f[i][j][p][q]\) 表示还剩 \(1\) 张有 \(i\) 种牌的,还剩 \(2\) 张牌的有 \(j\) 种,还剩 \(3\) 张牌的有 \(p\) 种,还剩 \(4\) 张牌的有

扑克牌顺子

题目描述 LL今天心情特别好,因为他去买了一副扑克牌,发现里面居然有2个大王,2个小王(一副牌原本是54张^_^)...他随机从中抽出了5张牌,想测测自己的手气,看看能不能抽到顺子,如果抽到的话,他决定去买体育彩票,嘿嘿!!"红心A,黑桃3,小王,大王,方片5","Oh My God!"不是顺子.....LL不高兴了,他想了想,决定大\小 王可以看成任何数字,并且A看作1,J为11,Q为12,K为13.上面的5张牌就可以变成"1,2,3,4,5"

2-08. 用扑克牌计算24点(25) (ZJU_PAT 数学 枚举)

题目链接:http://pat.zju.edu.cn/contests/ds/2-08 一副扑克牌的每张牌表示一个数(J.Q.K分别表示11.12.13,两个司令都表示6).任取4张牌,即得到4个1~13的数,请添加运算符(规定为加+ 减- 乘* 除/ 四种)使之成为一个运算式.每个数只能参与一次运算,4个数顺序可以任意组合,4个运算符任意取3个且可以重复取.运算遵从一定优先级别,可加括号控制,最终使运算结果为24.请输出一种解决方案的表达式,用括号表示运算优先.如果没有一种解决方案,则输出-1

JAVA学习面向对象之 扑克牌(初)

感想: 一开始不了解或者说是对JAVA的特性不熟悉,不知道类与类之间的联系,对JAVA的封装,继承,多态不熟悉和没有更好的理解,在以后的学习过程中要掌握并熟悉JAVA的开发习惯, 在写代码过程中还有众多东西没有掌握,靠着老师和同学的帮助完成这次学习,初步了解了JAVA面向对象开发的基本要领.写这个博客以便于自己今后学习,也算是一段美好的回忆吧! 上面是一个类图  表示着写这个程序的只要思路. Card类:他的下级是cardview上级是player,有着一定的关系 package com.cqv

算法题7 判断扑克牌中的顺子

题目: 来源 http://www.cnblogs.com/python27/archive/2011/11/27/2264405.html 随机抽取扑克牌中的n张牌,判断是不是顺子,即这5张牌是不是连续的.其中A看成1,J看成11,Q看成12,K看成13,大小王可以看成任何需要的数字. 分析: 对于扑克牌来说,数字范围是很明确的,1到K外加大小王(设定为M).假如这副牌是个顺子,也就是每张牌都不相同,那么利用一个大小为14的辅助数组counts[]就可以快速的实现排序,记录每张牌出现的次数,然

BZOJ 1816: [Cqoi2010]扑克牌( 二分答案 )

二分答案.. 一开始二分的初始右边界太小了然后WA,最后一气之下把它改成了INF... ------------------------------------------------------------------------ #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #define rep( i , n ) for( int i = 0 ; i

扑克牌

假定一副新扑克牌的顺序为:大王.小王.黑桃A,2,3,…,T,J,Q,K.红心A,2,3,…,T,J,Q,K.方块 A,2,3,…,T,J,Q,K.梅花A,2,3,…,T,J,Q,K.现将两副扑克牌摞放在一起,然后将最上面的一张牌舍去,将之后的一张牌移到整副牌 的最下面,重复此过程.问:最后剩下的是哪张牌? 1 #include<iostream> 2 using namespace std; 3 class Sqlist //用循环链表 4 { 5 public: 6 struct Node

【剑指offer】:Q44:扑克牌的顺子

def IsContinuous(seq, num = 5): zeros = 0; d = 0 seq = sorted(seq) for i in range(num - 1): if seq[i] == 0: zeros += 1 continue if seq[i] == seq[i + 1]: return False d += seq[i + 1] - seq[i] - 1 return zeros >= d [剑指offer]:Q44:扑克牌的顺子,布布扣,bubuko.com

用扑克牌保存文本信息

事实上,本文是在Peter Jerde的How much information can be stored by ordering 52 playing cards文章基础上翻译.改编和扩展而来的.当然这是经过Jerde本人首肯的. 注意本文方法并非最优,也没有完全利用所有的信息空间,只是简单的尝试. 有数字的地方就有信息.所以扑克牌中保存信息不是什么新鲜事. PDF文档点这里:下载 原文(英文)点这里:访问 这里有两个DEMO. 编码DEMO,解码DEMO 首先是"DEEP IN SHALL