P2668 斗地主

题目描述

牛牛最近迷上了一种叫斗地主的扑克游戏。斗地主是一种使用黑桃、红心、梅花、方片的A到K加上大小王的共54张牌来进行的扑克牌游戏。在斗地主中, 牌的大小关系根据牌的数码表示如 下:3<4<5<6<7<8<9<10<J<Q<K<A<2<小 王<大王,而花色并不对牌的大小产生影响。每一局游戏中,一副手牌由n张牌组成。游戏者每次可以根据规定的牌型进行出牌,首先打光自己的手牌一方取 得游戏的胜利。

现在,牛牛只想知道,对于自己的若干组手牌,分别最少需要多少次出牌可以将它们打光。请你帮他解决这个问题。

需要注意的是,本题中游戏者每次可以出手的牌型与一般的斗地主相似而略有不同。

具体规则如下:

本题数据随机,不支持hack,要hack或强力数据请点击这里

输入输出格式

输入格式:

第一行包含用空格隔开的2个正整数T和n,表示手牌的组数以及每组手牌的张数。

接下来T组数据,每组数据n行,每行一个非负整数对aibi表示一张牌,其中ai示牌的数码,bi表示牌的花色,中间用空格隔开。特别的,我们用1
来表示数码A,11表示数码J,12表示数码Q,13表示数码K;黑桃、红心、梅花、方片分别用1-4来表示;小王的表示方法为01,大王的表示方法为
02。

输出格式:

共T行,每行一个整数,表示打光第i手牌的最少次数。

输入输出样例

输入样例#1:

1 8
7 4
8 4
9 1
10 4
11 1
5 1
1 4
1 1
输出样例#1:

3
输入样例#2:

1 17
12 3
4 3
2 3
5 4
10 2
3 3
12 2
0 1
1 3
10 1
6 2
12 1
11 3
5 2
12 4
2 2
7 2
输出样例#2:

6

说明

样例1说明

共有1组手牌,包含8张牌:方片7,方片8,黑桃9,方片10,黑桃J,黑桃5,方片A以及黑桃A。可以通过打单顺子(方片7,方片8,黑桃9,方片10,黑桃J),单张牌(黑桃5)以及对子牌(黑桃A以及方片A)在3次内打光。

对于不同的测试点, 我们约定手牌组数T与张数n的规模如下:

数据保证:所有的手牌都是随机生成的。

95分。。。卡到极限了,尽力了

 #include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <queue>
#define min(a, b) ((a) < (b) ? (a) : (b))
#define max(a, b) ((a) > (b) ? (a) : (b)) inline void swap(int &x, int &y)
{
long long tmp = x;x = y;y = tmp;
} inline void read(int &x)
{
x = ;char ch = getchar(), c = ch;
while(ch < '' || ch > '')c = ch, ch = getchar();
while(ch <= '' && ch >= '')x = x * + ch - '', ch = getchar();
if(c == '-')x = -x;
} const int INF = 0x3f3f3f3f; int t, n, cnt[], tmp, ans, tmp2, tmp3, tmp4;
char s[]; //当前正在打第step步, 剩余now个
void dfs(int step, int now)
{
ans = min(ans, step - + now);
if(step > ans)return;
//枚举三顺子
if(tmp3 > && now >= )
{
for(register int i = ;i <= ;++ i)
{
if(cnt[i] > && cnt[i + ] >= )
{
cnt[i] -= , cnt[i + ] -= ;
tmp3 -= ;tmp2 -= ;
dfs(step + , now - );
register int j = i + ;
int t = ;
for(;j <= ;++ j)
{
if(tmp3 < )break;
if(cnt[j] > ) cnt[j] -= , ++ t, tmp3 -= , tmp2 -= , dfs(step + , now - (j - i + ) * );
else break;
}
-- j;
for(;j >= i + ;-- j) cnt[j] += ;
cnt[i] += , cnt[i + ] += ;
tmp3 += + t;tmp2 += + t;
}
}
}
//枚举双顺子
if(tmp2 > && now >= )
{
for(register int i = ;i <= ;++ i)
{
if(cnt[i] > && cnt[i + ] >= && cnt[i + ] >= )
{
cnt[i] -= , cnt[i + ] -= , cnt[i + ] -= ;
tmp2 -= ;
dfs(step + , now - );
register int j = i + ;
int t = ;
for(;j <= ;++ j)
{
if(tmp2 < )break;
if(cnt[j] > ) cnt[j] -= , tmp2 -= , dfs(step + , now - (j - i + ) * );
else break;
}
-- j;
for(;j >= i + ;-- j) cnt[j] += ;
cnt[i] += , cnt[i + ] += , cnt[i + ] += ;
tmp2 += + t;
}
}
}
//枚举单顺子
if(now >= )
{
for(register int i = ;i <= ;++ i)
{
if(cnt[i] && cnt[i + ] && cnt[i + ] && cnt[i + ] && cnt[i + ])
{
-- cnt[i], -- cnt[i + ], -- cnt[i + ], -- cnt[i + ], -- cnt[i + ];
int t3 = , t4 = , t2 = ;
if(cnt[i] == ) -- tmp4, ++ t4;
if(cnt[i + ] == ) -- tmp4, ++ t4;
if(cnt[i + ] == ) -- tmp4, ++ t4;
if(cnt[i + ] == ) -- tmp4, ++ t4;
if(cnt[i + ] == ) -- tmp4, ++ t4;
if(cnt[i] > ) -- tmp3, ++ t3;
if(cnt[i + ] > ) -- tmp3, ++ t3;
if(cnt[i + ] > ) -- tmp3, ++ t3;
if(cnt[i + ] > ) -- tmp3, ++ t3;
if(cnt[i + ] > ) -- tmp3, ++ t3;
if(cnt[i] > ) -- tmp2, ++ t2;
if(cnt[i + ] > ) -- tmp2, ++ t2;
if(cnt[i + ] > ) -- tmp2, ++ t2;
if(cnt[i + ] > ) -- tmp2, ++ t2;
if(cnt[i + ] > ) -- tmp2, ++ t2;
dfs(step + , now - );
register int j = i + ;
for(;j <= ;++ j)
if(cnt[j])
{
-- cnt[j];
if(cnt[j] == )++ t4, -- tmp4;
if(cnt[j] > ) ++ t3, -- tmp3;
if(cnt[j] > ) ++ t2, -- tmp2;
dfs(step + , now - (j - i + ));
}
else break;
-- j;
for(;j >= i + ;-- j) ++ cnt[j];
++ cnt[i], ++ cnt[i + ], ++ cnt[i + ], ++ cnt[i + ], ++ cnt[i + ];
tmp2 += t2, tmp3 += t3, tmp4 += t4;
}
}
}
//找四带二对牌
if(tmp4 && tmp2 > && now >= )
{
for(register int i = ;i <= ;++ i)
if(cnt[i] == )
for(register int j = ;j <= ;++ j)
if(cnt[j] > && i != j)
for(register int k = j + ;k <= ;++ k)
if(cnt[k] > && i != k)
{
cnt[j] -= ;
cnt[k] -= ;
cnt[i] -= ;
tmp2 -= ;
tmp3 -= ;
tmp4 -= ;
dfs(step + , now - );
cnt[j] += ;
cnt[k] += ;
cnt[i] += ;
tmp2 += ;
tmp3 += ;
tmp4 += ;
}
}
//找四带二单牌
if(tmp4 && now >= )
{
for(register int i = ;i <= ;++ i)
if(cnt[i] == )
{
for(register int j = ;j <= ;++ j)
if(cnt[j] > && i != j)
for(register int k = j + ;k <= ;++ k)
if(cnt[k] > && i != k)
{
int t2 = , t3 = , t4 = ;
-- cnt[j];
-- cnt[k];
if(cnt[j] == ) -- tmp4, ++ t4;
if(cnt[j] > ) -- tmp3, ++ t3;
if(cnt[j] > ) -- tmp2, ++ t2;
if(cnt[k] == ) -- tmp4, ++ t4;
if(cnt[k] > ) -- tmp3, ++ t3;
if(cnt[k] > ) -- tmp2, ++ t2;
cnt[i] -= ;
tmp4 -= ;
tmp3 -= ;
tmp2 -= ;
dfs(step + , now - );
++ cnt[j];
++ cnt[k];
cnt[i] += ;
tmp4 += + t4;
tmp3 += + t3;
tmp2 += + t2;
}
if(cnt[] > )
{
cnt[] -= ;
cnt[i] -= ;
tmp4 -= ;
tmp2 -= ;
dfs(step + , now - );
tmp4 += ;
tmp2 += ;
cnt[] += ;
cnt[i] += ;
}
}
}
//找三带二
if(tmp3 && tmp2 && now >= )
{
for(register int i = ;i <= ;++ i)
if(cnt[i] > )
for(register int j = ;j <= ;++ j)
if(cnt[j] > && i != j)
{
cnt[j] -= ;
cnt[i] -= ;
tmp2 -= ;
tmp3 -= ;
dfs(step + , now - );
cnt[j] += ;
cnt[i] += ;
tmp2 += ;
tmp3 += ;
}
}
//找三带一
if(tmp3 && now >= )
{
for(register int i = ;i <= ;++ i)
if(cnt[i] > )
{
cnt[i] -= ;
int t2 = , t3 = , t4 = ;
if(cnt[i] == ) -- tmp4, ++ t4;
if(cnt[i] > ) -- tmp3, ++ t3;
if(cnt[i] > ) -- tmp2, ++ t2;
tmp3 -= ;
tmp2 -= ;
dfs(step + , now - );
cnt[i] += ;
tmp3 += + t3;
tmp2 += + t2;
tmp4 += t4;
for(register int j = ;j <= ;++ j)
if(cnt[j] > && i != j)
{
int t1 = , t2 = , t3 = ;
if(cnt[j] == ) -- tmp4, ++ t4;
if(cnt[j] > ) -- tmp3, ++ t3;
if(cnt[j] > ) -- tmp2, ++ t2;
cnt[j] -= ;
cnt[i] -= ;
tmp3 -= ;
tmp2 -= ;
dfs(step + , now - );
cnt[j] += ;
cnt[i] += ;
tmp4 + t4;
tmp3 += + t3;
tmp2 += + t2;
}
}
}
//找裸四
if(tmp4 > )
{
for(register int i = ;i <= ;++ i)
if(cnt[i] == )
{
cnt[i] -= ;
tmp4 -= ;
tmp3 -= ;
tmp2 -= ;
dfs(step + , now - );
cnt[i] += ;
tmp4 += ;
tmp3 += ;
tmp2 += ;
}
}
//找对子
if(tmp2 > )
{
for(register int i = ;i <= ;++ i)
if(cnt[i] > )
{
cnt[i] -= ;
tmp2 -= ;
dfs(step + , now - );
tmp2 += ;
cnt[i] += ;
}
}
} int main()
{
read(t), read(n);
for(;t;-- t)
{
memset(cnt, , sizeof(cnt));
ans = n;
for(register int j = ;j <= n;++ j)
{
tmp4 = tmp2 = tmp3 = ;
s[] = s[] = ;
scanf("%s", s + );
if(s[] == '') ++ cnt[];
else if(s[] == '') ++ cnt[];
else if(s[] == '' && s[] == '') ++ cnt[];
else if(s[] == '' && s[] == '') ++ cnt[];
else if(s[] == '' && s[] == '') ++ cnt[];
else if(s[] == '' && s[] == '') ++ cnt[];
else if(s[] == '') ++ cnt[];
else ++ cnt[s[] - ''];
for(register int i = ;i <= ;++ i)
{
if(cnt[i] > ) ++ tmp2;
if(cnt[i] > ) ++ tmp3;
if(cnt[i] == ) ++ tmp4;
}
scanf("%s", s + );
}
dfs(, n);
printf("%d\n", ans);
}
return ;
}

TYVJ4239

TYVJ4239 [NOIP2015提高组DayT3]斗地主的更多相关文章

  1. NOIP2015提高组D1T3 斗地主

    问一副排n张,n<=23最少打几次打完,数据组数T<=100. 面向数据编程.. 前30分:乱暴力?没有顺子,把单.对子.炸弹.三张.王炸.三带一判一次即可. 前70分:状压,先预处理哪些 ...

  2. 【题解】NOIP2015提高组 复赛

    [题解]NOIP2015提高组 复赛 传送门: 神奇的幻方 \([P2615]\) 信息传递 \([P2661]\) 斗地主 \([P2668]\) 跳石头 \([P2678]\) 子串 \([P26 ...

  3. [NOIP2015] 提高组 洛谷P2615 神奇的幻方

    题目描述 幻方是一种很神奇的N*N矩阵:它由数字1,2,3,……,N*N构成,且每行.每列及两条对角线上的数字之和都相同. 当N为奇数时,我们可以通过以下方法构建一个幻方: 首先将1写在第一行的中间. ...

  4. 洛谷-神奇的幻方-NOIP2015提高组复赛

    题目描述 幻方是一种很神奇的N*N矩阵:它由数字1,2,3,--,N*N构成,且每行.每列及两条对角线上的数字之和都相同. 当N为奇数时,我们可以通过以下方法构建一个幻方: 首先将1写在第一行的中间. ...

  5. 洛谷 P2678 & [NOIP2015提高组] 跳石头

    题目链接 https://www.luogu.org/problemnew/show/P2678 题目背景 一年一度的“跳石头”比赛又要开始了! 题目描述 这项比赛将在一条笔直的河道中进行,河道中分布 ...

  6. 【数据结构】运输计划 NOIP2015提高组D2T3

    [数据结构]运输计划 NOIP2015提高组D2T3 >>>>题目 [题目描述] 公元 2044 年,人类进入了宇宙纪元.L 国有 n 个星球,还有 n−1 条双向航道,每条航 ...

  7. 【二分查找】 跳石头NOIP2015提高组 D2T1

    [二分查找]跳石头NOIP2015提高组 D2T1 >>>>题目 [题目描述] 一年一度的“跳石头”比赛又要开始了! 这项比赛将在一条笔直的河道中进行,河道中分布着一些巨大岩石 ...

  8. 刷题总结——子串(NOIP2015提高组)

    题目: 题目背景 NOIP2015 提高组 Day2 T2 题目描述 有两个仅包含小写英文字母的字符串 A 和 B .现在要从字符串 A 中取出 k 个互不重叠的非空子串,然后把这 k 个子串按照其在 ...

  9. noip2015 提高组 day1t1 神奇的幻方

    题目描述 幻方是一种很神奇的N*N矩阵:它由数字1,2,3,--,N*N构成,且每行.每列及两条对角线上的数字之和都相同. 当N为奇数时,我们可以通过以下方法构建一个幻方: 首先将1写在第一行的中间. ...

随机推荐

  1. php中date() 函数

    实例 格式化本地日期和时间,并返回格式化的日期字符串: <?php // Prints the day echo date("l") . "<br>&q ...

  2. CF1158F Density of subarrays

    CF1158F Density of subarrays 首先可以发现,有值的p最大是n/c 对于密度为p,每个数至少出现c次,且其实是每出现c个数,就分成一段,这样贪心就得到了p %ywy n/c ...

  3. python数据类型初始1

    int: 1,2,3就是用于计算. bool:主要是用于判断,True,False str:用引号引起来的,'dsldgau','张三'.主要用于储存少量数据,进行操作 list(列表):[1,2,3 ...

  4. adb环境部署及与模拟器的连接

    1.下载adt-bundle-windows-x64安装包,下载网址https://www.7down.com/soft/293453.html 2.对安装包进行解压缩 3.配置环境变量,将adb的路 ...

  5. charles-过滤网络请求方法

    方法一:在主界面的中部的 Filter 栏中填入需要过滤出来的关键字.例如我们的服务器的地址是:https://www.baidu.com , 那么只需要在 Filter 栏中填入 https://w ...

  6. Mobox 知识管理平台助推市长质量奖

    Mobox 知识管理平台助推市长质量奖 引言: 在过去的十多年中,国际上在管理领域出现两股浪潮:一是许多国家和地区采取设立政府质量奖的方式,来改善企业管理绩效,提升区域整体竞争力:二是这些国家和地区的 ...

  7. [转]C# 中的委托和事件 + 观察者模式

    引言 委托 和 事件在 .Net Framework中的应用非常广泛,然而,较好地理解委托和事件对很多接触C#时间不长的人来说并不容易.它们就像是一道槛儿,过了这个槛的人,觉得真是太容易了,而没有过去 ...

  8. 【hihocoder 1477】闰秒

    [题目链接]:http://hihocoder.com/problemset/problem/1477 [题意] 中文题 [题解] 首先,一年一年地加,把开始的年份和结束的年份之间的年根据是否为闰年; ...

  9. linux服务器项目搭建常用命令

    linux下载链接文件 wget -c 后面是该网络地址和文件的位置. 例如:wget -c http://apache.opncas.or/MySQL/MySQL-7/v7.0.67/bin/MyS ...

  10. 在skyline中将井盖、雨水箅子等部件放到地面模型上

    公司三维建模组遇到这样的一个问题,怎样将井盖.雨水盖子恰好放在做好的地面模型上.传统的方法是在skyline中逐个调整井盖的对地高度,就是调整为恰好能放在地面上.或者选择很粗糙的一个方法,在“高度”属 ...