[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 考虑对于每一个人单独算 每一个人有两种情况,翻倍和不翻倍,他的名次不变等价于大于等于他的人数不变 设当前考虑的人的成 ...
随机推荐
- layui 监听switch事件
<input type="checkbox" lay-filter="common_change_status" name="switch&qu ...
- urlencode编码 — 为什么要编码
原文链接:https://blog.csdn.net/stpeace/article/details/82892571 参考:https://blog.csdn.net/z69183787/artic ...
- 【LEETCODE】45、766. Toeplitz Matrix
package y2019.Algorithm.array; /** * @ProjectName: cutter-point * @Package: y2019.Algorithm.array * ...
- 使用 Issue 管理软件项目详解
文章来源:http://www.ruanyifeng.com/blog/2017/08/issue.html 软件开发(尤其是商业软件)离不开项目管理,Issue 是最通用的管理工具之一. 本文介绍 ...
- 企业级容器管理平台 Rancher 介绍入门及如何备份数据
企业级容器管理平台 Rancher 介绍入门及如何备份数据 是什么 Rancher 是一个为 DevOps 团队提供的完整的 Kubernetes 与容器管理解决方案的开源的企业级容器管理平台.它解决 ...
- Spring AOP创建BeforeAdvice和AfterAdvice实例
BeforeAdvice 1.会在目标对象的方法执行之前被调用. 2.通过实现MethodBeforeAdvice接口来实现. 3.该接口中定义了一个方法即before方法,before方法会在目标对 ...
- 线程池ThreadPool实战
线程池ThreadPool 线程池概念 常用线程池和方法 1.测试线程类 2.newFixedThreadPool固定线程池 3.newSingleThreadExecutor单线程池 4.newCa ...
- 【CH1809】匹配统计(KMP)
题目链接 摘自https://www.cnblogs.com/wyboooo/p/9829517.html 用KMP先求出以a[i]为结尾的前缀与b匹配的最长长度. 比如 f[i] = j,就表示a[ ...
- rabbitmq保证数据不丢失方案
rabbitmq如何保证消息的可靠性 1.保证消息不丢失 1.1.开启事务(不推荐) 1.2.开启confirm(推荐) 1.3.开启RabbitMQ的持久化(交换机.队列.消息) 1.4.关闭Rab ...
- iOS自动签名网站
node.js作为服务端,调用shell脚本进行iOS包重签名. 需要安装:nodejs ,forever 安装环境: 安装nodejs 安装forever: npm install forever ...