斗地主[NOIP2015]
题目描述
牛牛最近迷上了一种叫斗地主的扑克游戏。斗地主是一种使用黑桃、红心、梅花、方片的A到K加上大小王的共54张牌来进行的扑克牌游戏。在斗地主中,牌的大小关系根据牌的数码表示如下:3<4<5<6<7<8<9<10<J<Q<K<A<2<小王<大王,而花色并不对牌的大小产生影响。每一局游戏中,一副手牌由n张牌组成。游戏者每次可以根据规定的牌型进行出牌,首先打光自己的手牌一方取得游戏的胜利。现在,牛牛只想知道,对于自己的若干组手牌,分别最少需要多少次出牌可以将它们打光。请你帮他解决这个问题。需要注意的是,本题中游戏者每次可以出手的牌型与一般的斗地主相似而略有不同。具体规则如下:

输入
第一行包含用空格隔开的2个正整数T,N,表示手牌的组数以及每组手牌的张数。
接下来T组数据,每组数据N行,每行一个非负整数对Ai,Bi,表示一张牌,其中Ai表示牌的数码,Bi表示牌的花色,中间用空格隔开。特别的,我们用1来表示数码A,11表示数码J,12表示数码Q,13表示数码K;黑桃、红心、梅花、方片分别用1-4来表示;小王的表示方法为01,大王的表示方法为02。
输出
输共T行,每行一个整数,表示打光第T组手牌的最少次数。
样例输入1
1 8
7 4
8 4
9 1
10 4
11 1
5 1
1 4
1 1
样例输出1
3
样例说明:共有1组手牌,包含8张牌:方片7,方片8,黑桃9,方片10,黑桃J,黑桃5,方片A以及黑桃A。可以通过打单顺子(方片7,方片8,黑桃9,方片10,黑桃J),单张牌(黑桃5)以及对子牌(黑桃A以及方片A)在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
数据范围
对于不同的测试点, 我们约定手牌组数T与张数n的规模如下:

数据保证:所有的手牌都是随机生成的。
时空限制
1024M,2s
【题解】
一道喜闻乐见的大模拟大搜索题,看到了之后就一直跃跃欲试想做一做。考试主要的时间都用来打这道题,刚开始是bfs,卡到直接死机。后来改成dfs,成功过了样例,水过6个点。总觉得dfs不如bfs适合找最优解,但是其实dfs也可以通过剪枝遏制不必要的搜索,而像这种情况非常多的题目bfs要尝试每一种情况的下一步,消耗过大反而不适宜。
正解也是暴搜,但是搜得比我有技巧多了。尽量先打出较多牌来剪枝,最后那些没有被各种特效打出去的牌就直接一视同仁st++就好了。在考试代码上加了最后这条优化瞬间从TLE变成AC,其实想想打单种牌这么简单的事,一句话就解决了何必再来一层dfs呢~据说这道题体现了用各种条件层层剪枝的重要性,但是对于我来说,还是对所谓的“高明的处理方法”更有体会吧。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int t,n,p[],a1,a2,jg;
bool qk;
void init()
{
memset(p,,sizeof(p));
for(int i=;i<=n;i++)
{
scanf("%d%d",&a1,&a2);
if(a1==) p[]++;
if(a1==) p[]++;
if(a1>) p[a1-]++;
if(!a1)
{
if(a2==) p[]++;
if(a2==) p[]++;
}
}
}
void dfs(int st)
{
if(st>=jg) return;
qk=;
int ss,sz,sf;
ss=sz=sf=;
for(int i=;i<=;i++)
{
if(p[i]) qk=;
if(p[i]>=) sz++;
if(p[i]>=) ss++;
if(p[i]>=) sf++;
}
if(qk)
{
jg=st;
return;
}
if(st==jg-) return; int temp;
temp=;
for(int i=temp+;i<=;i++)
if(p[i])
{
temp=i;
for(int j=i+;j<=;j++)
{
if(p[j]) temp=j;
else break;
}
if(temp>=i+)
{
for(int j=i;j<=temp;j++) p[j]--;
st++;
dfs(st);
for(int j=i;j<=temp;j++) p[j]++;
st--;
}
temp++;
}
if(sz>=)
{
temp=;
for(int i=temp+;i<=;i++)
if(p[i]>=)
{
temp=i;
for(int j=i+;j<=;j++)
{
if(p[j]>=) temp=j;
else break;
}
if(temp>=i+)
{
for(int j=i;j<=temp;j++) p[j]-=;
st++;
dfs(st);
for(int j=i;j<=temp;j++) p[j]+=;
st--;
}
if(temp-i+==sz) break;
temp++;
}
}
if(ss>=)
{
temp=;
for(int i=temp+;i<=;i++)
if(p[i]>=)
{
temp=i;
for(int j=i+;j<=;j++)
{
if(p[j]>=) temp=j;
else break;
}
if(temp>=i+)
{
for(int j=i;j<=temp;j++) p[j]-=;
st++;
dfs(st);
for(int j=i;j<=temp;j++) p[j]+=;
st--;
}
if(temp-i+==ss) break;
temp++;
}
} if(sf)
for(int i=;i<=;i++)
if(p[i]>=)
{
p[i]-=,st++;
for(int j=;j<=;j++)
if(p[j])
{
p[j]--;
for(int jk=j;jk<=;jk++)
if(p[jk])
{
p[jk]--;
dfs(st);
p[jk]++;
}
p[j]++;
}
if(sz>=)
{
for(int j=;j<=;j++)
if(p[j]>=)
{
p[j]-=;
for(int jk=j;jk<=;jk++)
if(p[jk]>=)
{
p[jk]-=;
dfs(st);
p[jk]+=;
}
p[j]+=;
}
}
p[i]+=;
st--;
if(sf==) break;
} if(ss)
for(int i=;i<=;i++)
if(p[i]>=)
{
p[i]-=,st++;
for(int j=;j<=;j++)
if(p[j]&&j!=i)
{
p[j]--;
dfs(st);
p[j]++;
}
if(sz)
for(int j=;j<=;j++)
if(p[j]>=)
{
p[j]-=;
dfs(st);
p[j]+=;
}
p[i]+=,st--;
if(ss==) break;
} if(p[]&&p[])
{
p[]--,p[]--,st++;
dfs(st);
p[]++,p[]++,st--;
} for(int i=;i<=;i++)
if(p[i])
st++;
if(st<jg) jg=st;
}
int main()
{
scanf("%d%d",&t,&n);
for(int l=;l<=t;l++)
{
init();
jg=0x3fff;
dfs();
printf("%d\n",jg);
}
return ;
}
landlords
斗地主[NOIP2015]的更多相关文章
- 斗地主 (NOIP2015 Day1 T3)
斗地主 张牌,因为它可以连在K后, 总体思路为 先出炸弹和四带二 再出三带一 再把对牌和单牌出完 记录并更新Answer,后枚举顺子,并继续向下搜索. 注意:弄明白题意,题目描述不太清楚....另外, ...
- 洛谷P2668 斗地主 [NOIP2015]
题目描述 牛牛最近迷上了一种叫斗地主的扑克游戏.斗地主是一种使用黑桃.红心.梅花.方片的A到K加上大小王的共54张牌来进行的扑克牌游戏.在斗地主中,牌的大小关系根据牌的数码表示如下:3<4< ...
- NOIP2015斗地主[DFS 贪心]
题目描述 牛牛最近迷上了一种叫斗地主的扑克游戏.斗地主是一种使用黑桃.红心.梅花.方片的A到K加上大小王的共54张牌来进行的扑克牌游戏.在斗地主中,牌的大小关系根据牌的数码表示如下:3<4< ...
- BZOJ 4325: NOIP2015 斗地主
4325: NOIP2015 斗地主 Time Limit: 30 Sec Memory Limit: 1024 MBSubmit: 684 Solved: 456[Submit][Status] ...
- NOIP2015 斗地主(搜索+剪枝)
4325: NOIP2015 斗地主 Time Limit: 30 Sec Memory Limit: 1024 MBSubmit: 270 Solved: 192[Submit][Status] ...
- [补档][NOIP2015] 斗地主
[NOIP2015] 斗地主 题目 传送门:http://cogs.pro/cogs/problem/problem.php?pid=2106 INPUT 第一行包含用空格隔开的2个正整数Tn,表示手 ...
- LOJ2422 NOIP2015 斗地主 【搜索+贪心】*
LOJ2422 NOIP2015 斗地主 LINK 题目大意很简单,就是问你斗地主的一分手牌最少多少次出完 然后我们发现对于一种手牌状态,不考虑顺子的情况是可以贪心做掉的 然后我们直接枚举一下顺子出牌 ...
- 【BZOJ4325】NOIP2015 斗地主 搜索+剪枝
[BZOJ4325]NOIP2015 斗地主 Description 牛牛最近迷上了一种叫斗地主的扑克游戏.斗地主是一种使用黑桃.红心.梅花.方片的A到K加上大小王的共54张牌来进行的扑克牌游戏.在斗 ...
- 2106. [NOIP2015] 斗地主
2106. [NOIP2015] 斗地主 ★★★☆ 输入文件:landlords.in 输出文件:landlords.out 简单对比 时间限制:2 s 内存限制:1025 M ...
随机推荐
- 一篇文章让你搞懂 SSL 证书
关于结婚这件事 那天和同事讨论到底什么才算是真正的「结婚」?这种话题本来是极其不应该存在的.传统意义的领个证书,办个婚礼.吃吃喝喝,但随着社会各族人民身心发展进化,原本那些繁琐流程简直是反人类,貌似现 ...
- RabbitMQ windows安装官方文档翻译!
RabbitMQ Windows安装和配置 下载地址 官网windows下载地址: http://www.rabbitmq.com/releases/rabbitmq-server/v3.6.10/r ...
- Linux用户管理-中
添加用户组命令groupadd 提示:groupadd命令的使用非常简单,但在生产环境中使用的不多,因此,会简单应用即可. 与groupadd命令有关的文件有:/etc/group :用户组相关文件/ ...
- Exception in thread "main" java.lang.NoClassDefFoundError: javax/transaction/Synchronization
解决办法:原因是缺少jta.jar包,添加jta.jar包就好
- CSS三种引入方式:内联、页级、外联
1.内联CSS 内联CSS也可称为行内CSS或者行级CSS,它直接在标签内部引入,显著的优点是十分的便捷.高效:但是同时也造成了不能够重用样式的缺点,如果代码行数到达一定长度不建议采用.通常内联CSS ...
- Makefile学习总结
Makefile用法分析 在linux开发中,应用程序的编译基本都采用GNU的make工具,而make搭配Makefile来实现工程代码的编译,在越是大型复杂的项目中,make的强悍之处越是明 ...
- 使用C#创建简单的WCF服务
一.开发环境 操作系统:Windows 10 开发环境:VS2015 编程语言:C# IIS版本:10.0.0.0 二.添加WCF服务.Internet Information Services(II ...
- 我眼中的ASP.NET Core之微服务 (二)
前言 接上一篇. 上一篇未完待续的原因是当时刚好是6-30号晚上马上12点了还没写完,然后我想赶在7月1号之前发出去,所以当时就发了.然后在发的时候出了一点问题,结果发出去的时候刚好是 7.1号 00 ...
- docker~大叔对术语的解释
回到目录 接触和使用docker已经有1年多了,起初对概念本身理解的不是很好,或者说,没有找到一本比较好的书,在自己的研究下,对docker一些基本的概念有了自己的一些认识和看法,现在分享给正在学习d ...
- poj_1679: The Unique MST【次小生成树】
题目链接 参考博客 希望注释足够清楚..欢迎指出不足~ #include<cstdio> #include<cstring> #include<algorithm> ...