题目描述

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

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

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

具体规则如下:

输入输出格式

输入格式:

第一行包含用空格隔开的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的规模如下:

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

dp+深搜版

1 8
3 1
3 2
3 3
5 1
5 2
5 3
8 1
8 2
8 3

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
const int MAXN=;
int T,n,p,hs,ans;
int dp[MAXN][MAXN][MAXN][MAXN],card_num[MAXN],happen[MAXN/];
int take_num[]={,,,};
int read(int & n)
{
char c='-';int x=;
while(c<''||c>'')c=getchar();
while(c>=''&&c<='')
{
x=x*+(c-);
c=getchar();
}
n=x;
}
int calc(int one,int two,int three,int four,int king)
{
if(king==)// 只有一张大小王
{
one++;// 看做单牌处理
king=;
}
if(king==)
return dp[four][three][two][one];
else
return min(dp[four][three][two][one+],dp[four][three][two][one]+);
}
void dfs(int now)//now是指已经操作的次数
{
if(now>ans)
return ;
memset(happen,,sizeof(happen));// 初始化
for(int i=;i<=;i++)
happen[card_num[i]]++;
ans=min(ans,now+calc(happen[],happen[],happen[],happen[],card_num[]));
for(int k=;k<=;k++)// 顺子
{
for(int i=;i<=;i++)
{
int j;
for(j=i;j<=&&card_num[j]>=k;j++)
{
card_num[j]-=k;
if(j-i+>=take_num[k])
dfs(now+);
}
for(j--;j>=i;j--)
card_num[j]+=k;
}
}
}
int main()
{
// freopen("landlords.in","r",stdin);
// freopen("landlords.out","w",stdout);
read(T);read(n);
memset(dp,,sizeof dp);
dp[][][][]=;
// dp[i][j][k][l]表示打出i套四张,j套三张,k套两站,l张单牌所需要的最少步数
for(int i=;i<=n;i++)//四张
for(int j=;j<=n;j++)//三张
for(int k=;k<=n;k++)//两张
for(int l=;l<=n;l++)//一张
if(i*+j*+k*+l*<=n)
{
dp[i][j][k][l]=i+j+k+l;//最坏的情况
if(i)
{
if(k>=)
dp[i][j][k][l]=min(dp[i][j][k][l],dp[i-][j][k-][l]+);
// 四带一对对牌
if(l>=)
dp[i][j][k][l]=min(dp[i][j][k][l],dp[i-][j][k][l-]+);
// 一对单牌
dp[i][j][k][l]=min(dp[i][j][k][l],dp[i-][j][k][l]+);
//啥都不带
}
if(j)
{
if(k)
dp[i][j][k][l]=min(dp[i][j][k][l],dp[i][j-][k-][l]+);
// 3带对
if(l)
dp[i][j][k][l]=min(dp[i][j][k][l],dp[i][j-][k][l-]+);
// 3带单
dp[i][j][k][l]=min(dp[i][j][k][l],dp[i][j-][k][l]+);
// 什么都不带
}
if(k)
dp[i][j][k][l]=min(dp[i][j][k][l],dp[i][j][k-][l]+);
if(l)
dp[i][j][k][l]=min(dp[i][j][k][l],dp[i][j][k][l-]+);
}
while(T--)
{
memset(card_num,,sizeof(card_num));// 初始化
ans=n;
for(int i=;i<=n;i++)
{
read(p);read(hs);
if(p==)
card_num[]++;//大小王
else if(p==)
card_num[]++;// A
else card_num[p]++;
}
dfs();
printf("%d\n",ans);
}
return ;
}

P2668 斗地主 dp+深搜版的更多相关文章

  1. P2668 斗地主 贪心+深搜

    题目描述 牛牛最近迷上了一种叫斗地主的扑克游戏.斗地主是一种使用黑桃.红心.梅花.方片的A到K加上大小王的共54张牌来进行的扑克牌游戏.在斗地主中,牌的大小关系根据牌的数码表示如下:3<4< ...

  2. 洛谷 P2392 kkksc03考前临时抱佛脚, dp / 深搜

    题目链接 P2392 kkksc03考前临时抱佛脚 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 题目 dp代码 #include <iostream> #includ ...

  3. ZOJ1100 状压DP +深搜

    记得做过类似于这类题目是能够用组合数学方法来解决的,可惜淡忘了,也找不到了,看了网上的也有人提到过能够用组合公式解决,但是没人做,都是用了状压DP的方法,这个状压非常难讲清楚吧,推荐两篇 第一遍大体看 ...

  4. hdoj--3666--THE MATRIX PROBLEM(差分约束+SPFA深搜)

    THE MATRIX PROBLEM Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Other ...

  5. 深搜+DP剪枝 codevs 1047 邮票面值设计

    codevs 1047 邮票面值设计 1999年NOIP全国联赛提高组  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond 题目描述 Description ...

  6. 方格取数(多线程dp,深搜)

    https://www.luogu.org/problem/P1004 题目描述 设有N×N的方格图(N≤9),我们将其中的某些方格中填入正整数,而其他的方格中则放入数字0.如下图所示(见样例): 某 ...

  7. Luogu P2668 斗地主(NOIP2015)

    还记得那道我只用特判得了30分的"斗地主"吗? 我今天脑抽打算把它改A掉.为什么不用这大好时光去干些更有意义的事 于是我就挖了这个坑. 题解: 题目链接:P2668 斗地主 本题就 ...

  8. ACM 海贼王之伟大航路(深搜剪枝)

    "我是要成为海贼王的男人!" 路飞他们伟大航路行程的起点是罗格镇,终点是拉夫德鲁(那里藏匿着"唯一的大秘宝"--ONE PIECE).而航程中间,则是各式各样的 ...

  9. HDU 4597 Play Game(记忆化搜索,深搜)

    题目 //传说中的记忆化搜索,好吧,就是用深搜//多做题吧,,这个解法是搜来的,蛮好理解的 //题目大意:给出两堆牌,只能从最上和最下取,然后两个人轮流取,都按照自己最优的策略,//问说第一个人对多的 ...

随机推荐

  1. Centos6.4安装Zimbra初步教程

    环境: 1.centos6.4*64位版本 2.主机最好内存设置在2G以上,要不安装的时候卡死你 3.下载最新的开源的Zimbra安装包,下载zcs-8.0.4_GA_5737.RHEL6_64.20 ...

  2. HDU 1030 数学题

    给出两点,求这两点在图上的最短路径 分别以最上,左下,右下为顶点,看这个三角图形 ans=这三种情况下两点的层数差 #include "stdio.h" #include &quo ...

  3. UVa 1531 - Problem Bee

    题目:如图所看到的的蜂巢型的图中.蜜蜂想从A点飞到B点,假设A与B不在同一个正六边形中, 则它先飞到A的中心.每次飞到相邻格子的中心,最后飞到B的中心,再飞到B点: 假设在一个格子中.直接飞过去就可以 ...

  4. Ckeditor通过Ajax更新数据

    之前在表单中对ckeditor的赋值就直接是 $("#theadEditor").val(result); 而如今我想通过点击不同选项来使用Ajax在后台訪问数据.对ckedito ...

  5. react 项目实战(八)图书管理与自动完成

    图书管理 src / pages / BookAdd.js   // 图书添加页 /** * 图书添加页面 */ import React from 'react'; // 布局组件 import H ...

  6. keepalived + lvs marster 与 backup 之间的 高可用

    简介 keepalived 是linux下一个轻量级的高可用解决方案,它与HACMP实现功能类似,都可以实现服务或者网络的高可用,但是又有差别:hacmp是一个专业的.功能完善的高可用软件,它提供了H ...

  7. Cocos2d-x学习笔记(12)(CCControlSwitch开关、CCControlSlider滑动条、CCControlButtonbutton)

    CCEditBox.CCControlSwitch.CCControlSlider.CCControlColourPicker.CCControlButton等都是Cocos2d-x 2.x的最新UI ...

  8. Lunix

    1.Lunix系统登录.重启.关闭 ①.登录 ②.重启 ③.关闭:shutdown [选项][时间][警告信息] -k 向所有用户发出警告信息 -r 关机后立即重启 -h 关机后不重新启动 -f 快速 ...

  9. swift 笔记 (二十一) —— 高级运算符

    高级运算符 位运算符 按位取反: ~ 按位与运算:  & 按位或运算:  | 按位异或运算:  ^ 按位左移运算: << 按位右移动算: >> 溢出运算符 自从swif ...

  10. redis 的部分配置

    linux 安装: yum install redis 修改redis配置: 配置文件位于/etc/redis.conf. 作为守护进程运行(默认no) # 默认情况下 redis 不是作为守护进程运 ...