NOIp2015D1T3 斗地主【暴搜】
刚开始读到题目的时候,非常懵逼,非常崩溃,写着写着呢,也有点崩溃,细节有点多。
这个做法呢,只能过掉官方数据,洛谷上好像有加强版,只能得$86$分,就没有管了。
大概说一下思路:
暴力搜索每一种可能的情况,如果可以就递归下去,然后回溯。
搜索框架的话,大概就是把当前搜到的出牌次数传到参数里面,如果参数已经大于了当前的最小答案就剪枝退出。然后在当前状态下枚举每一种出牌的情况,能够出就出,然后递归到下一层,参数出牌次数+1。
可以证明不会无限递归下去,因为在参数已经大于了当前的最小答案的时候就退出了。
可以分为三大类出牌:顺子、带牌、散牌
还有一些细节什么的:
1.把$A$放在$K$后面,顺子的时候比较方便
2.$2$不能在顺子里面(当时还理解了好久$2$点是什么,还以为是什么其他代称...)
3.王。之前以为王只可以单出或者火箭,没有认真读题,王是可以被带的,但是只能带单牌,王不能看成一对,他们牌值不一样。
4.后来发现顺子和带牌打完之后,可以不用单独考虑打散牌(单牌,对子,三张牌),因为如果剩下,$1$次就可以打出去一种,而且无论如何只打$1$次用的打牌次数会最少。而且散牌不用考虑与其他牌的组合。(可以感性理解,次数最多肯定是每一次都按种数打散牌)
#include<cstdio>
#include<algorithm>
#include<vector>
#include<cstring>
#include<queue>
#include<map>
#include<iostream>
using namespace std;
#define ll long long
#define INF 0x3f3f3f3f
#define N 30
int rd()
{
int f=,s=;char c=getchar();
while(c<''||c>''){if(c=='-') f=-;c=getchar();}
while(c>=''&&c<=''){s=(s<<)+(s<<)+(c^);c=getchar();}
return f*s;
}
//J->11 Q->12 K->13 A->14 2->15 King->16
//王特殊处理 只能出火箭或者单出(糟糕 还可以单带
//2不能出顺子
int n,ans;
int cnt[N];
void dfs(int res)
{
if(res>=ans) return ;//剪枝 提前退出
/*
//-----炸弹
for(int i=3;i<=15;i++)
if(cnt[i]>=4)
{
cnt[i]-=4;
dfs(res+1);
cnt[i]+=4;
}
//-----
//-----对子牌
for(int i=3;i<=15;i++)
if(cnt[i]>=2)
{//2个对子...就是炸弹了 应该在前面判断过了
cnt[i]-=2;
dfs(res+1);
cnt[i]+=2;
}
//-----
//-----三张牌
for(int i=3;i<=15;i++)
if(cnt[i]>=3)
{
cnt[i]-=3;
dfs(res+1);
cnt[i]+=3;
}
//-----
*/
//-----顺子
//---单顺子
int k=;
for(int i=;i<=;i++)//不包括2点
{
if(cnt[i]==) k=;//顺子断了 从这里重新开始
else//否则就接下去
{
k++;
if(k>=)
{
for(int j=i;j>=i-k+;j--)
cnt[j]--;
dfs(res+);
for(int j=i;j>=i-k+;j--)
cnt[j]++;
}
}
}
//---
//---双顺子
k=;
for(int i=;i<=;i++)//不包括2点
{
if(cnt[i]<) k=;//顺子断了 从这里重新开始
else//否则就接下去
{
k++;
if(k>=)
{
for(int j=i;j>=i-k+;j--)
cnt[j]-=;
dfs(res+);
for(int j=i;j>=i-k+;j--)
cnt[j]+=;
}
}
}
//---
//---三顺子
k=;
for(int i=;i<=;i++)//不包括2点
{
if(cnt[i]<) k=;//顺子断了 从这里重新开始
else//否则就接下去
{
k++;
if(k>=)
{
for(int j=i;j>=i-k+;j--)
cnt[j]-=;
dfs(res+);
for(int j=i;j>=i-k+;j--)
cnt[j]+=;
}
}
}
//---
//-----
//-----带牌
for(int i=;i<=;i++)
{
if(cnt[i]<) continue;
//3带X
cnt[i]-=;
for(int j=;j<=;j++)
{
if(i==j) continue;
if(cnt[j]>=)
{
cnt[j]--;
dfs(res+);
cnt[j]++;
}
if(cnt[j]>=&&j!=/*王不能一起带*/)
{
cnt[j]-=;
dfs(res+);
cnt[j]+=;
}
}
cnt[i]+=;
//4带X(两个单张或两个对)
if(cnt[i]<) continue;
cnt[i]-=;
for(int j=;j<=;j++)
{
if(i==j||cnt[j]<=) continue;
cnt[j]--;//两张单牌
for(int k=;k<=;k++)
{
if(k==j||k==i||cnt[k]<) continue;
cnt[k]--;
dfs(res+);
cnt[k]++;
}
cnt[j]++;
if(cnt[j]<||j==/*王不能一起*/) continue;
cnt[j]-=;//两对对子
for(int k=;k<=;k++)
{
if(k==j||k==i||cnt[k]<) continue;
cnt[k]-=;
dfs(res+);
cnt[k]+=;
}
cnt[j]+=;
}
cnt[i]+=;
}
//-----
for(int i=;i<=;i++)
if(cnt[i]) res++;
//突然发现 单张 对子三张都不用特殊考虑 反正能一次出完剩下的所有牌
ans=min(ans,res);
}
int main()
{
int T=rd(),n=rd();
while(T--)
{
memset(cnt,,sizeof(cnt));
ans=INF;
for(int i=;i<=n;i++)
{
int m=rd(),opt=rd();
if(m==) m=;
if(m==) m=;
if(m==) m=;
cnt[m]++;
}
dfs();
printf("%d\n",ans);
}
return ;
}
Code
NOIp2015D1T3 斗地主【暴搜】的更多相关文章
- 【BZOJ-3033】太鼓达人 欧拉图 + 暴搜
3033: 太鼓达人 Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 204 Solved: 154[Submit][Status][Discuss] ...
- c++20701除法(刘汝佳1、2册第七章,暴搜解决)
20701除法 难度级别: B: 编程语言:不限:运行时间限制:1000ms: 运行空间限制:51200KB: 代码长度限制:2000000B 试题描述 输入正整数n,按从小到大的顺序输出所有 ...
- Codeforces Round #238 (Div. 2) D. Toy Sum 暴搜
题目链接: 题目 D. Toy Sum time limit per test:1 second memory limit per test:256 megabytes 问题描述 Little Chr ...
- poj 3080 Blue Jeans(水题 暴搜)
题目:http://poj.org/problem?id=3080 水题,暴搜 #include <iostream> #include<cstdio> #include< ...
- Sicily1317-Sudoku-位运算暴搜
最终代码地址:https://github.com/laiy/Datastructure-Algorithm/blob/master/sicily/1317.c 这题博主刷了1天,不是为了做出来,AC ...
- codeforces 339C Xenia and Weights(dp或暴搜)
转载请注明出处: http://www.cnblogs.com/fraud/ ——by fraud Xenia and Weights Xenia has a set of weig ...
- Usaco 2.3 Zero Sums(回溯DFS)--暴搜
Zero SumConsider the sequence of digits from 1 through N (where N=9) in increasing order: 1 2 3 ... ...
- HDU4403(暴搜)
A very hard Aoshu problem Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & ...
- suoi62 网友跳 (暴搜+dp)
传送门 sbw太神啦orz 首先N<=20可以直接暴搜 然后玄学剪枝可以过18个点 那么N<=40的时候,就把它拆成两半分别暴搜,再用dp拼起来 对于前半段,设f[i][j]是开始高度为i ...
- bzoj1016/luogu4208 最小生成树计数 (kruskal+暴搜)
由于有相同权值的边不超过10条的限制,所以可以暴搜 先做一遍kruskal,记录下来每个权值的边使用的数量(可以离散化一下) 可以证明,对于每个权值,所有的最小生成树中选择的数量是一样的.而且它们连成 ...
随机推荐
- php类知识---try catch
<?php try { echo "比赛开始"."\n"; ); } catch (Exception $e ) { echo "获取错误信息: ...
- es6的Set结构
今天看了一下es6的文档,发现还是比较实用的,Set结构可以用来数组的去重哎 let arr = [1,3,6,3,1,9] let arr1 = new Set(arr) [...arr1]的值就是 ...
- html跳转Controller的路径的问题
- c语言函数分析
1.vc6的相关使用 1)常用的快捷键 f7 ->编译 f5 ->运行 f9 ->断点 f10 ->单步执行 f11 ->单步执行,可进入函 ...
- [winafl]这几天的折腾
1.自己写的exe 2.自己写的dll,然后写了接口程序去load...但是这个速度真是迷醉 先把基本的几种类型跑起来,再解决速度和样本的问题...
- CDOJ 1263 The Desire of Asuna 贪心
The Desire of Asuna Time Limit: 3000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Othe ...
- 【CUDA 基础】3.2 理解线程束执行的本质(Part I)
title: [CUDA 基础]3.2 理解线程束执行的本质(Part I) categories: CUDA Freshman tags: 线程束分化 CUDA分支 toc: true date: ...
- 灰度图像--图像分割 Robert算子
学习DIP第43天 转载请标明本文出处:http://blog.csdn.net/tonyshengtan,欢迎大家转载,发现博客被某些论坛转载后,图像无法正常显示,无法正常表达本人观点,对此表示很不 ...
- C库函数-fgets()
函数声明:char *fgets(char *str,int n,FILE *stream) 函数介绍:从指定的stream流中读取一行,并把它存储在str所指向的字符串中.当读取到(n-1)个字符时 ...
- JavaWeb-SpringBoot(抖音)_三、抖音项目后续
JavaWeb-SpringBoot(抖音)_一.抖音项目制作 传送门 JavaWeb-SpringBoot(抖音)_二.服务器间通讯 传送门 JavaWeb-SpringBoot(抖音)_三.抖音项 ...