P2668 斗地主 dp+深搜版
题目描述
牛牛最近迷上了一种叫斗地主的扑克游戏。斗地主是一种使用黑桃、红心、梅花、方片的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 8
7 4
8 4
9 1
10 4
11 1
5 1
1 4
1 1
3
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
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+深搜版的更多相关文章
- P2668 斗地主 贪心+深搜
题目描述 牛牛最近迷上了一种叫斗地主的扑克游戏.斗地主是一种使用黑桃.红心.梅花.方片的A到K加上大小王的共54张牌来进行的扑克牌游戏.在斗地主中,牌的大小关系根据牌的数码表示如下:3<4< ...
- 洛谷 P2392 kkksc03考前临时抱佛脚, dp / 深搜
题目链接 P2392 kkksc03考前临时抱佛脚 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 题目 dp代码 #include <iostream> #includ ...
- ZOJ1100 状压DP +深搜
记得做过类似于这类题目是能够用组合数学方法来解决的,可惜淡忘了,也找不到了,看了网上的也有人提到过能够用组合公式解决,但是没人做,都是用了状压DP的方法,这个状压非常难讲清楚吧,推荐两篇 第一遍大体看 ...
- hdoj--3666--THE MATRIX PROBLEM(差分约束+SPFA深搜)
THE MATRIX PROBLEM Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Other ...
- 深搜+DP剪枝 codevs 1047 邮票面值设计
codevs 1047 邮票面值设计 1999年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description ...
- 方格取数(多线程dp,深搜)
https://www.luogu.org/problem/P1004 题目描述 设有N×N的方格图(N≤9),我们将其中的某些方格中填入正整数,而其他的方格中则放入数字0.如下图所示(见样例): 某 ...
- Luogu P2668 斗地主(NOIP2015)
还记得那道我只用特判得了30分的"斗地主"吗? 我今天脑抽打算把它改A掉.为什么不用这大好时光去干些更有意义的事 于是我就挖了这个坑. 题解: 题目链接:P2668 斗地主 本题就 ...
- ACM 海贼王之伟大航路(深搜剪枝)
"我是要成为海贼王的男人!" 路飞他们伟大航路行程的起点是罗格镇,终点是拉夫德鲁(那里藏匿着"唯一的大秘宝"--ONE PIECE).而航程中间,则是各式各样的 ...
- HDU 4597 Play Game(记忆化搜索,深搜)
题目 //传说中的记忆化搜索,好吧,就是用深搜//多做题吧,,这个解法是搜来的,蛮好理解的 //题目大意:给出两堆牌,只能从最上和最下取,然后两个人轮流取,都按照自己最优的策略,//问说第一个人对多的 ...
随机推荐
- 打开Eclipse出现“An internal error has occurred. java.lang.NullPointerException
今天打开eclipse出现了这个问题:下面是老外给出的办法,粘给大家: Instead of deleting the whole .metadata folder, just delete the ...
- Ubuntu 16.04重启输入法
一般使用搜狗输入法,但是偶尔不太稳定会挂掉,但是可以通过以下脚本重启: pidof fcitx | xargs kill pidof sogou-qimpanel | xargs kill nohup ...
- Spring Boot多数据源连接8小时后断开的问题解决(MySQL)
这个问题涉及的方面很多,需要一步步去排查,可能环境有问题,数据库有问题,但是网上最多的应该是如下的方式去解决. 以单个数据源为主,多个数据源基本方法一致. 1.MySQL 5版本之前可以通过在URL后 ...
- 系统无法安装 OfficeControl.ocx 控件如何解决
在OA上要直接查看word等公告文件,就必须安装office控件.要安装office控件,需要在IE浏览器中做相应的设置.如何设置呢,下面由小编具体介绍下. 工具/原料 OA IE浏览器 方法 ...
- spring mvc随便接收list<objeect>参数
在后台设定一个类,PersonList类: public class PersonList {private List<User> user; public List<User> ...
- Base Conversion In PHP and javascript
http://www.exploringbinary.com/base-conversion-in-php-using-built-in-functions/ http://www.binarycon ...
- yarn使用
参数中有中括号和尖括号,我们要识别以下区别: [] :可选项 <>:必选项 初始化一个新的项目 yarn init 添加一个依赖包 yarn add [package] yarn add ...
- HDU 1231——最大连续子序列(DP)
最大连续子序列 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Su ...
- 调试 Android* x86 应用程序的方法以及要使用的工具
作者:Xiaodong Wang 1.简单介绍 众所周知,Android* 开发者头顶很多称呼:设计员.程序员等,而且一般会不可避免地被称为故障检修工. 代码中的错误无法避免.因此不管您是否一開始就造 ...
- union关键字及大小端模式
1. union 关键字 union 维护足够的空间来置放多个数据成员中的“一种”,而不是为每一个数据成员配置空间,在 union 中所有的数据成员共用一个空间,同一时间只能储存其中一个数据成员,所有 ...