[NOIp 2015]斗地主
Description
牛牛最近迷上了一种叫斗地主的扑克游戏。斗地主是一种使用黑桃、红心、梅花、方片的A到K加上大小王的共54张牌来进行的扑克牌游戏。在斗地主中,牌的大小关系根据牌的数码表示如下:3<4<5<6<7<8<9<10<J<Q<K<A<2<小王<大王,而花色并不对牌的大小产生影响。每一局游戏中,一副手牌由n张牌组成。游戏者每次可以根据规定的牌型进行出牌,首先打光自己的手牌一方取得游戏的胜利。现在,牛牛只想知道,对于自己的若干组手牌,分别最少需要多少次出牌可以将它们打光。请你帮他解决这个问题。需要注意的是,本题中游戏者每次可以出手的牌型与一般的斗地主相似而略有不同。具体规则如下:
Input
第一行包含用空格隔开的2个正整数T,N,表示手牌的组数以及每组手牌的张数。
Output
共T行,每行一个整数,表示打光第T组手牌的最少次数。
Sample Input
7 4
8 4
9 1
10 4
11 1
5 1
1 4
1 1
Sample Output
HINT
共有1组手牌,包含8张牌:方片7,方片8,黑桃9,方片10,黑桃J,黑桃5,方
题解
抓取有用信息:
出牌顺序不影响出牌次数。
30分算法:
1、$T≤100$,$n≤4$;
2、先特判掉三带一的情况,然后有几种不同点数的牌,答案就是几;注意两张王可以看成是相同点数;
3、时间复杂度$O(T*n)$
100分算法:
1、$T≤10$,$n≤23$;
2、既然出牌顺序不影响,那么不妨先出对子,包括单顺、双顺、三顺。具体就是直接暴力枚举每一个顺子,然后出掉,再枚举顺子,再出掉......
3、这样可以过吗?
一个顺子至少有$5$张牌,最多出$4$组顺子,递归层数很小;
然后在一组牌内可以产生$O(K^2)$个顺子,其中$K$表示能成为顺子组成部分的牌的种数,在这里$K=12$,然后这里的复杂度就是$O(K^8)$,看起来很大,其实实测完全可以跑出来;
4、然后就可以不考虑顺子了,那么对于剩下的牌,我们就只能一个一个或者一对一对或者一带一带地出,也就是说出牌次数与牌的点数无关了;
5、那么我们可以预处理一个$dp[a][b][c][d]$,表示手牌有"$d$张单牌,$c$个对子,$b$个三张,$a$个炸弹"的时候,把牌出完的最少次数。
6、可以动态规划求解,$joker$可以拿出单独讨论。
7、时间复杂度$O(n^4+T*K^8)$。
这道题还有数据增强版,就是多考虑几个条件,把牌拆开(详见代码中的$extra$)。
#include <set>
#include <map>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <cstdio>
#include <string>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define LL long long
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define Min(a, b) ((a) < (b) ? (a) : (b))
using namespace std;
const int INF = ~0u>>;
const int lenth[] = {, , , }; int n, t;
int card[], f[][][][];
int ans; int getrest(int r1, int r2, int r3, int r4, int joker){
if (joker == ) r1++,joker--;
if (joker) return Min(f[r4][r3][r2][r1+], f[r4][r3][r2][r1]+);
return f[r4][r3][r2][r1];
}
void dfs(int t){
if (t >= ans) return;
int c[] = {};
for (int i = ; i <= ; i++) c[card[i]]++;
ans = Min(ans, t+getrest(c[], c[], c[], c[], card[]));
for (int len = ; len <= ; len++)
for (int i = ; i <= ; i++){
int j = i;
for (;j <= && card[j] >= len; j++){
card[j] -= len;
if (j-i+ >= lenth[len]) dfs(t+);
}
for (j--; j >= i; j--) card[j] += len;
}
}
void pre(){
memset(f, /, sizeof(f));
f[][][][] = ;
for (int i = ; i <= n; i++)
for (int j = ; j <= n; j++)
for (int p = ; p <= n; p++)
for (int q = ; q <= n; q++)
if (i*+j*+p*+q <= n)
{
f[i][j][p][q] = i+j+p+q;
if (i){
if (p >= ) f[i][j][p][q] = Min(f[i][j][p][q], f[i-][j][p-][q]+);//四带两对
if (q >= ) f[i][j][p][q] = Min(f[i][j][p][q], f[i-][j][p][q-]+);//四带二
if (p) f[i][j][p][q] = Min(f[i][j][p][q], f[i][j][p-][q+]);//extra:把对子拆成一个单的
f[i][j][p][q] = Min(f[i][j][p][q], f[i-][j][p+][q]);//extra:把炸拆成两对
f[i][j][p][q] = Min(f[i][j][p][q], f[i-][j+][p][q+]);//extra:把炸拆成单张和三张
f[i][j][p][q] = Min(f[i][j][p][q], f[i-][j][p][q]+);//出炸
}
if (j){
if (p) f[i][j][p][q] = Min(f[i][j][p][q], f[i][j-][p-][q]+);//三带一对
if (q) f[i][j][p][q] = Min(f[i][j][p][q], f[i][j-][p][q-]+);//三带一
f[i][j][p][q] = Min(f[i][j][p][q], f[i][j-][p+][q+]);//extra:三拆成二+一
f[i][j][p][q] = Min(f[i][j][p][q], f[i][j-][p][q]+);//直接出三张
}
if (p) f[i][j][p][q] = Min(f[i][j][p][q], f[i][j][p-][q]+);//直接出对子
if (q) f[i][j][p][q] = Min(f[i][j][p][q], f[i][j][p][q-]+);//直接出单张
}
} int main(){
scanf("%d%d", &t, &n);
pre();
while (t--){
memset(card, , sizeof(card));
int a, b;
ans = n;
for (int i = ; i <= n; i++){
scanf("%d%d", &a, &b);
if (a == ) card[]++;
else card[a]++;
}
dfs();
printf("%d\n", ans);
}
return ;
}
[NOIp 2015]斗地主的更多相关文章
- Luogu 2668 NOIP 2015 斗地主(搜索,动态规划)
Luogu 2668 NOIP 2015 斗地主(搜索,动态规划) Description 牛牛最近迷上了一种叫斗地主的扑克游戏.斗地主是一种使用黑桃.红心.梅花.方片的A到K加上大小王的共54张牌来 ...
- 基础算法(搜索):NOIP 2015 斗地主
Description 牛牛最近迷上了一种叫斗地主的扑克游戏.斗地主是一种使用黑桃.红心.梅花.方片的A到K加上大小王的共54张牌来进行的扑克牌游戏.在斗地主中,牌的大小关系根据牌的数码表示如下:3& ...
- [BZOJ 4325][NOIP 2015] 斗地主
一道防AK好题 4325: NOIP2015 斗地主 Time Limit: 30 Sec Memory Limit: 1024 MBSubmit: 820 Solved: 560[Submit] ...
- [NOIP 2015] 斗地主 landlord
想起几个月之前的 noip2015-只会瞎搞-这道题骗了 30 分.T T 题目 牛牛最近迷上了一种叫斗地主的扑克游戏.斗地主是一种使用黑桃.红心.梅花.方片的 A 到 K 加上大小王的共 54 张牌 ...
- noip 2015 斗地主 大爆搜!!!
反正肯定是大模拟 但是每一个可以出的牌都搜一定不是最优的 考虑最特殊的出牌方案:顺子(单,对,三) 每一种方案再加上暴力贪心打出剩下的牌的步数 #include<cstdio> #incl ...
- 洛谷 P2668 & P2540 [ noip 2015 ] 斗地主 —— 搜索+贪心
题目:https://www.luogu.org/problemnew/show/P2668 https://www.luogu.org/problemnew/show/P2540 首先,如果没有 ...
- 4632 NOIP[2015] 运输计划
4632 NOIP[2015] 运输计划 时间限制: 1 s 空间限制: 256000 KB 题目等级 : 大师 Master 题解 题目描述 Description 公元 2044 ...
- NOIP 2015
Prob.1 2015 神奇的幻方 模拟就好了.(这不是noip2017的初赛题么.)代码: #include<cstdio> #include<cstring> #inclu ...
- [NOIP 2015]运输计划-[树上差分+二分答案]-解题报告
[NOIP 2015]运输计划 题面: A[NOIP2015 Day2]运输计划 时间限制 : 20000 MS 空间限制 : 262144 KB 问题描述 公元 2044 年,人类进入了宇宙纪元. ...
随机推荐
- Beta敏捷冲刺每日报告——Day3
1.情况简述 Beta阶段Scrum Meeting 敏捷开发起止时间 2017.11.4 00:00 -- 2017.11.5 00:00 讨论时间地点 2017.11.4 晚9:30,电话会议会议 ...
- 2018上C语言程序设计(高级)作业- 第2次作业
作业要求一 提交截图: 6-7: 6-8: 6-9: 7-1: 作业要求二 题目6-7删除字符中数字字符 1.设计思路: (1)第一步:本题要求是删除字符中的数字字符,我的主要思路是通过数组遍历若遇到 ...
- JAVA线程概念
一.操作系统中线程和进程的概念 现在的操作系统是多任务操作系统.多线程是实现多任务的一种方式. 进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程中可以启动多个线程.比如在 ...
- 【iOS】OC-UTC日期字符串格式化
NSLog(@"%@",[NSDate date]); NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init ...
- Syabse数据库无法启动的解决方案
在探讨本问题之前,首先要为大家解释一下Syabse数据库本身.Syabse数据库应用和本身的架构相对而言都相对比较复杂,多数技术人员及公司对Sybase数据库底层结构和运行机制也处于并非完全了解的阶段 ...
- $.each遍历json数组
1.遍历单层json数组 我们把idx和obj都打印出来看看,到底是什么东西 var json1 =[{"id":"1","tagName" ...
- JAVA_SE基础——43.抽象类
高手勿喷~ 抽象类:当定义一个类时,常常需要定义一些方法来描述该类的行为特征,但有时这些方法的实现方式是无法确定的.例如定义Animal类时,shout()方法用于表示动物的叫声,但是针对不同的动物, ...
- Highcharts tooltip显示多条线的信息
直接上代码吧,简单粗暴点: tooltip: { shared: true, valueSuffix: '分', formatter: function () { let s = "&quo ...
- Linux CentOS7.0 (01)在Vmvare Workstation上 安装配置
一.新建虚拟机 1.创建新的虚拟机 -> 默认典型 ->选择安装介质 2.指定虚拟机名称.安装目录.磁盘容量大小 点击 "完成",创建虚拟机! 随后虚拟机将自动启动安装 ...
- hadoop2.6.0实践:控制台入口url列表
hadoop web控制台页面的端口整理: 50070:hdfs文件管理 8088:ResourceManager 8042:NodeManager 19888:JobHistory(使用" ...