[PKUSC2018]主斗地
暴搜
非常暴力的搜索,以至于我都不相信我能过。
方法是:暴力枚举所有牌型,然后暴力判断是否可行。
暴力枚举部分:
非常暴力:
void dfs(int x,int l){
if(l==0){
flag=0;
check(1,0,0,0,0);
if(flag)ans++;
return;
}
if(x>14)return;
for(res i=0;i<=limit[x]&&i<=l;++i){
jiry[x]=i;
dfs(x+1,l-i);
}
}
搜下来发现牌型数量不大于\(3000000\),因为出题人良心的把3都去掉了,所以总牌型大量缩减。
判断部分:
这里需要用到一个性质,如果一幅飞机或顺子可以大于另外一幅同类型的牌,那么把他拆开来也可以大于另外一幅牌拆开来。
判断部分分两部分,先暴力搜索搜出哪些牌要被拆出来变成三张牌或四张牌。
因为双方的总牌数都不会很大,所以直接搜只会带一个常数。
这里要注意,只有当九条可怜出了三张牌或四张牌以后,xx网友才能出三张牌或四张牌,不然九条可怜将无法出小于xx网友的牌型。
最后两者出的三张牌和四张牌数量必须相等,不然会有一副牌无法有对应的牌。
void check(int x,int one,int oneortwo,int three,int four){
if(x>14){
if(three||four)return;
check(one,oneortwo);
return;
}
if(jiry[x]>=4){
jiry[x]-=4;
check(x+1,one+1,oneortwo,three,four+1);
jiry[x]+=4;
if(flag)return;
}
if(jiry[x]>=3){
jiry[x]-=3;
check(x+1,one,oneortwo+1,three+1,four);
jiry[x]+=3;
if(flag)return;
}
if(xx[x]>=4&&four){
xx[x]-=4;
check(x+1,one,oneortwo,three,four-1);
xx[x]+=4;
if(flag)return;
}
if(xx[x]>=3&&three){
xx[x]-=3;
check(x+1,one,oneortwo,three-1,four);
xx[x]+=3;
if(flag)return;
}
check(x+1,one,oneortwo,three,four);
}
然后再用贪心的方式判断最后的散牌是否可以。
枚举有多少的三张牌要带一个,然后得到有多少的一张牌和多少的两张牌可以被带掉。
对于九条可怜的牌,去掉最大的牌。对于xx网友的牌,去掉最小的牌。要先用两张牌来贪心,再用一张牌来贪心。
剩下的牌直接扫一遍,如果在前\(i\)种牌中xx网友的牌比九条可怜的要多,则当前牌错误。
void check(int one,int oneortwo){
for(res i=0;i<=oneortwo;i++){
memcpy(jirycpy,jiry,sizeof jiry);
memcpy(xxcpy,xx,sizeof xx);
res o=i+one*2,t=oneortwo-i;
for(res j=1;j<=14;++j){
while(xxcpy[j]>=2&&t)xxcpy[j]-=2,t--;
while(xxcpy[j]>=1&&o)xxcpy[j]-=1,o--;
}
if(o||t)continue;
o=i+one,t=oneortwo-i;
for(res j=14;j;--j){
while(jirycpy[j]>=2&&t)jirycpy[j]-=2,t--;
while(jirycpy[j]>=1&&o)jirycpy[j]-=1,o--;
}
if(o||t)continue;
flag=1;
for(res j=1,now=0;j<=14;++j){
now-=xxcpy[j];
if(now<0){
flag=0;
break;
}
now+=jirycpy[j];
}
if(flag)return;
}
}
然后是完整代码
#include<bits/stdc++.h>
#define res register int
using namespace std;
char str[15];
int jiry[15],xx[15],limit[15];
int jirycpy[15],xxcpy[15];
int cl(char c){
if(c=='T')return 7;
else if(c=='J')return 8;
else if(c=='Q')return 9;
else if(c=='K')return 10;
else if(c=='A')return 11;
else if(c=='2')return 12;
else if(c=='w')return 13;
else if(c=='W')return 14;
else return c-'3';
}
bool flag;
int ans;
void check(int one,int oneortwo){
for(res i=0;i<=oneortwo;i++){
memcpy(jirycpy,jiry,sizeof jiry);
memcpy(xxcpy,xx,sizeof xx);
res o=i+one*2,t=oneortwo-i;
for(res j=1;j<=14;++j){
while(xxcpy[j]>=2&&t)xxcpy[j]-=2,t--;
while(xxcpy[j]>=1&&o)xxcpy[j]-=1,o--;
}
if(o||t)continue;
o=i+one,t=oneortwo-i;
for(res j=14;j;--j){
while(jirycpy[j]>=2&&t)jirycpy[j]-=2,t--;
while(jirycpy[j]>=1&&o)jirycpy[j]-=1,o--;
}
if(o||t)continue;
flag=1;
for(res j=1,now=0;j<=14;++j){
now-=xxcpy[j];
if(now<0){
flag=0;
break;
}
now+=jirycpy[j];
}
if(flag)return;
}
}
void check(int x,int one,int oneortwo,int three,int four){
if(x>14){
if(three||four)return;
check(one,oneortwo);
return;
}
if(jiry[x]>=4){
jiry[x]-=4;
check(x+1,one+1,oneortwo,three,four+1);
jiry[x]+=4;
if(flag)return;
}
if(jiry[x]>=3){
jiry[x]-=3;
check(x+1,one,oneortwo+1,three+1,four);
jiry[x]+=3;
if(flag)return;
}
if(xx[x]>=4&&four){
xx[x]-=4;
check(x+1,one,oneortwo,three,four-1);
xx[x]+=4;
if(flag)return;
}
if(xx[x]>=3&&three){
xx[x]-=3;
check(x+1,one,oneortwo,three-1,four);
xx[x]+=3;
if(flag)return;
}
check(x+1,one,oneortwo,three,four);
};
void dfs(int x,int l){
if(l==0){
flag=0;
check(1,0,0,0,0);
if(flag)ans++;
return;
}
if(x>14)return;
for(res i=0;i<=limit[x]&&i<=l;++i){
jiry[x]=i;
dfs(x+1,l-i);
}
}
int main(){
scanf("%s",str+1);
int len=strlen(str+1);
for(int i=1;i<=12;++i){
limit[i]=4;
}
limit[13]=limit[14]=1;
memset(xx,0,sizeof xx);
for(int i=1;i<=len;++i){
limit[cl(str[i])]--;
xx[cl(str[i])]++;
}
ans=0;
dfs(1,17);
printf("%d\n",ans);
}
[PKUSC2018]主斗地的更多相关文章
- [PKUSC2018]主斗地(搜索+贪心)
首先如果对子和三张牌出现在解中,那么全拆成单张显然没有问题,顺子同理.于是真正有用的牌型就只有单牌.三带一.三带二.四带二了. 暴搜jry手中的牌,然后先搜出双方的大牌型(即三张.四张牌的个数),再枚 ...
- 「PKUSC2018」主斗地(暴搜)
这道斗地主比 \(PKUWC\) 那道可做多了... 我们用 \(NOIP\) 那道斗地主的思路:暴搜出三代和四代,贪心出散牌. 还有jry为什么要出xx网友而不出他的另一个老婆 我们发现两个人的每回 ...
- 【LOJ】#6434. 「PKUSC2018」主斗地
题解 什么,我这题竟然快到了LOJ rk1???? 搜起来有点麻烦,不过感觉还是比斗地主好下手(至今没敢写斗地主 首先是暴力搜牌型,最多\(3^{16}\)(什么判解还要复杂度怂成一团)的样子?? 然 ...
- Loj#6434「PKUSC2018」主斗地(搜索)
题面 Loj 题解 细节比较多的搜索题. 首先现将牌型暴力枚举出来,大概是\(3^{16}\)吧. 然后再看能打什么,简化后无非就三种决策:单牌,\(3+x\)和\(4+x\). 枚举网友打了几张\( ...
- PKUSC2018题解
PKUSC2018题解 真实排名 分别考虑第\(i\)个人翻倍和不翻倍的情况,组合数算一下即可,务必注意实现细节. 代码 最大前缀和 设\(sum_s\)表示集合\(\sum_{i\in s} a_i ...
- 胡小兔的 PKUSC2018 游记
Day 0 一番纠结之后,我还是选择了 PKUSC (Penguin Kingdom University Summer Camp, 企鹅王国大学夏令营)! 理由?扔硬币决定的理由如下: PKU好啊 ...
- PKUWC/SC 做题笔记
去年不知道干了些啥,什么省选/营题都没做. 现在赶应该还来得及(?) 「PKUWC2018」Minimax Done 2019.12.04 9:38:55 线段树合并船新玩法??? \(O(n^2)\ ...
- PKUWC&SC 2018 刷题记录
PKUWC&SC 2018 刷题记录 minimax 线段树合并的题,似乎并不依赖于二叉树. 之前写的草率的题解在这里:PKUWC2018 minimax Slay the Spire 注意到 ...
- PKUSC 2018 题解
PKUSC 2018 题解 Day 1 T1 真实排名 Link Solution 考虑对于每一个人单独算 每一个人有两种情况,翻倍和不翻倍,他的名次不变等价于大于等于他的人数不变 设当前考虑的人的成 ...
随机推荐
- 【flask】登陆后返回之前重定向跳转的页面
登陆后返回之前重定向跳转的页面 一.前言 实现强制跳转到登陆页面,登陆后返回之前的页面的功能.网上跳登陆页面的很多:返回之前页面功能没多少.这里我只是用了自己的方法,有缺点和其他方法也请指点!(´ε` ...
- CMDB和自动化运维
CMDB和自动化运维 IT运维的分类 IT运维,指的是对已经搭建好的网络,软件,硬件进行维护.运维领域也是细分的,有硬件运维和软件运维 硬件运维主要包括对基础设施的运维,比如机房的设备,主机的硬盘,内 ...
- Android--Facebook Login without LoginButton
1.引入facebook 工程lib,在Manifest中声明com.facebook.LoginActivity,facebook_app_id <activity android:name= ...
- Mysql之锁的基本介绍
数据库锁定机制简单来说,就是数据库为了保证数据的一致性,而使各种共享资源在被并发访问变得有序所设计的一种规则.对于任何一种数据库来说都需要有相应的锁定机制,所以MySQL自然也不能例外.MySQL数据 ...
- 转 js一个简单实用的弹出层
关闭 点击查看 >> <html> <head> <title>新文件标题</title> <script type=" ...
- springboot笔记05——profile多环境配置切换
前言 一个应用程序从开发到上线,往往需要经历几个阶段,例如开发.测试.上线.每个阶段所用到的环境的配置可能都是不一样的,Springboot 应用可以很方便地在各个环境中对配置进行切换.所以,今天主要 ...
- SpringBoot中resources配置文件application.properties
#项目名server.servlet.context-path=/springboot-day1#端口号server.port=8989 #datasource数据库连接信息#urlspring.da ...
- 数据结构与算法(周测9-B树与B+树)
由于博主太菜,题目集还不完整,有待更新. 判断题 1.m阶B树的根结点最多有m棵子树. T F 2.In a B+ tree, leaves and nonleaf nodes h ...
- flutter apk 打包
https://blog.csdn.net/weixin_33738578/article/details/87998565 http://www.cnblogs.com/sangwl/p/10400 ...
- AJAX 初识
AJAX全称为 Asynchronous Javasript And XML,是在浏览器端进行网络编程(发送请求,接收响应)的技术方案.AJAX 也就是浏览器提供的一套API,可以供 Javascri ...