[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 考虑对于每一个人单独算 每一个人有两种情况,翻倍和不翻倍,他的名次不变等价于大于等于他的人数不变 设当前考虑的人的成 ...
随机推荐
- matlab调试时子函数断点不起作用
matlab调试代码时总是遇到这样一个奇怪的问题,就是当我在主程序(.m脚本)中调用子函数并在子函数中设置断点,然后开始调试运行主程序... 发现主程序直接运行到结束而并没有在调用子函数的时候在所设置 ...
- 怎么理解js的原型链继承?
前言 了解java等面向对象语言的童鞋应该知道.面向对象的三大特性就是:封装,继承,多态. 今天,我们就来聊一聊继承.但是,注意,我们现在说的是js的继承. 在js的es6语法出来之前,我们想实现js ...
- JXOI2018
发现自己不会T3可以退群了 排序问题(组合.模拟) 可以发现Gobo Sort相当于在所有排列中随机选择一个,所以当第\(i\)个数出现次数为\(a_i\)时,期望的Sort次数就是\(\frac{( ...
- 查看线程CPU利用率
查看线程CPU利用率 方法1:利用ps命令查看对应的线程 1. ps -ef | grep 进程名称 2. ps -mp 进程ID -o THREAD,pid,tid,cmd,time,%cpu,%m ...
- new Image 读取宽高为0——onload
获取图片一张图片的大小 let img = new Image() img.src = imgUrl if ( img.width != 375 || img.height != 200 ) { me ...
- NetCore实例提供的依赖注入的生命周期
Transient: 每一次GetService都会创建一个新的实例,每次从容器 (IServiceProvider)中获取的时候都是一个新的实例Scoped: 在同一个Scope内只初始化一个实例 ...
- 11.15java实习生面试总结
坐了两个小时的车,到了面试地点面了十五分钟左右就结束了,心里有一点难受,不过这也是刚开始,后面的路还长着呢,所以先把面试官问的题目记录下来. 1.C语言能否跨平台? 虽然我面的是java实习生,但是因 ...
- 【转载】C#中List集合使用Remove方法移除指定的对象
在C#的List集合操作中,有时候需要将特定的对象或者元素移除出List集合序列中,此时可使用到List集合的Remove方法,Remove方法的方法签名为bool Remove(T item),it ...
- 0.UML图入门——学习《大话设计模式》笔记
<大话设计模式>中讲述了UML类图的基本用法,做此笔记加深理解. 注:上图来源于<大话设计模式> 上图中设计的关键术语为:继承.实现.聚合.组合.关联.依赖. 要想弄清楚UML ...
- vuex页面刷新数据丢失的解决办法
在vue项目中用vuex来做全局的状态管理, 发现当刷新网页后,保存在vuex实例store里的数据会丢失. 原因: 因为store里的数据是保存在运行内存中的,当页面刷新时,页面会重新加载vue实例 ...