P2540 [NOIP2015 提高组] 斗地主 加强版
简要题意
给你一副手牌,求最少的次数出完所有手牌。(按照它给出的规定出)
题目
分析
因为求最小次数直接贪心很明显是错的,但又直接写不出 \(dp\) 的式子,所以我们只能够爆搜所有情况,但这样明显会超时,只有剪枝,我们记录了各个数码的个数,但其实除了顺子以外,其他的出牌并不关心数码的大小,只关心个数。所以我们单独处理顺子,然后只记录 \(js[i]\) 表示有 \(i\) 张牌的数码个数,然后在模拟出牌。这个时候我们发现,只要 \(js\) 一样答案就一样与先后顺序等无关,所以记忆化搜索(dp)记录一下就可以了。但一定要注意一些特殊情况,如双王可以当对子出,不能当对子用,有可能将三个的拆成一个和两个更优,同理四个拆成一个和三个或两个两个。
代码
点击查看代码
#include <bits/stdc++.h>
using namespace std;
int t,n,cnt[20],js[10],xz[5]={0,5,3,2};
int dp[30][30][30][30];
int dfs()
{
if(dp[js[1]][js[2]][js[3]][js[4]]!=-1)return dp[js[1]][js[2]][js[3]][js[4]];
int sum=n;
if(js[2])
{
js[2]--;js[1]+=2;
sum=min(sum,dfs());
js[2]++;js[1]-=2;
}//chai2
if(js[3])
{
js[3]--;js[1]+=1,js[2]+=1;
sum=min(sum,dfs());
js[3]++;js[1]-=1,js[2]-=1;
}
if(js[4])
{
js[4]--;js[1]+=1,js[3]+=1;
sum=min(sum,dfs());
js[4]++;js[1]-=1,js[3]-=1;
js[4]--;js[2]+=2;
sum=min(sum,dfs());
js[4]++;js[2]-=2;
}
if(js[1])js[1]--,sum=min(sum,1+dfs()),js[1]++;//danpai
if(js[2])js[2]--,sum=min(sum,1+dfs()),js[2]++;//duizi
if(js[3])js[3]--,sum=min(sum,1+dfs()),js[3]++;//san
if(js[4])js[4]--,sum=min(sum,1+dfs()),js[4]++;//炸弹
if(js[3]&&js[1])
{
js[3]--;js[1]--;
sum=min(sum,1+dfs());
js[3]++;js[1]++;
} //3+1
if(js[3]&&js[2])
{
js[3]--;js[2]--;
sum=min(sum,1+dfs());
js[3]++;js[2]++;
} //3+2
if(js[2]>=2&&js[4])
{
js[4]--;js[2]-=2;
sum=min(sum,1+dfs());
js[4]++;js[2]+=2;
}
if(js[1]>=2&&js[4])
{
js[4]--;js[1]-=2;
sum=min(sum,1+dfs());
js[4]++;js[1]+=2;
}//4+2
return dp[js[1]][js[2]][js[3]][js[4]]=min(sum,js[1]+js[2]+js[3]+js[4]);
}
int shunzi(int step)
{
int ans=n;
for(int k=1;k<=3;k++)
for(int i=1;i<=12-xz[k]+1;i++)
{
int tot=0;
for(int j=i;j<=12;j++)
{
if(cnt[j]>=k)tot++;
else break;
}
for(int j=i+xz[k]-1;j<=i+tot-1;j++)
{
// cout<<i<<" "<<j<<'\n';
for(int l=i;l<=j;l++)js[cnt[l]]--,cnt[l]-=k,js[cnt[l]]++;
ans=min(ans,shunzi(step+1));//可以出多个顺子
for(int l=i;l<=j;l++)js[cnt[l]]--,cnt[l]+=k,js[cnt[l]]++;
}
}
ans=min(ans,step+dfs());//出完顺子直接跑
if(cnt[14]==2)
{
js[1]-=2;
ans=min(step+1+dfs(),ans);//出个王炸再跑。
js[1]+=2;
}
return ans;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>t>>n;
memset(dp,-1,sizeof(dp));
dp[0][0][0][0]=0;
while(t--)
{
memset(cnt,0,sizeof(cnt));
memset(js,0,sizeof(js));
for(int i=1;i<=n;i++)
{
int ai,bi;cin>>ai>>bi;
if(ai>=1)
{
if(ai>=3)cnt[ai-2]++;
else cnt[ai+11]++;//A,2
}
else cnt[14]++;//wang
}
for(int i=1;i<=14;i++)js[cnt[i]]++;
if(cnt[14]&&cnt[14]==2)js[1]+=2,js[2]-=1;//处理双王
cout<<shunzi(0)<<'\n';
}
return 0;
}
反思
1.不要省一些极小的内存,增加代码长度,直接将数组当形参传入即可减少一半的长度,不用复原。
2.思考的不全面,一开始没有想到出完一个顺子后再出顺子,以及王炸当对子用(如三带二带王炸),以及开始写前没有充分思考。
P2540 [NOIP2015 提高组] 斗地主 加强版的更多相关文章
- 【题解】NOIP2015提高组 复赛
[题解]NOIP2015提高组 复赛 传送门: 神奇的幻方 \([P2615]\) 信息传递 \([P2661]\) 斗地主 \([P2668]\) 跳石头 \([P2678]\) 子串 \([P26 ...
- [NOIP2015] 提高组 洛谷P2615 神奇的幻方
题目描述 幻方是一种很神奇的N*N矩阵:它由数字1,2,3,……,N*N构成,且每行.每列及两条对角线上的数字之和都相同. 当N为奇数时,我们可以通过以下方法构建一个幻方: 首先将1写在第一行的中间. ...
- 洛谷-神奇的幻方-NOIP2015提高组复赛
题目描述 幻方是一种很神奇的N*N矩阵:它由数字1,2,3,--,N*N构成,且每行.每列及两条对角线上的数字之和都相同. 当N为奇数时,我们可以通过以下方法构建一个幻方: 首先将1写在第一行的中间. ...
- 洛谷 P2678 & [NOIP2015提高组] 跳石头
题目链接 https://www.luogu.org/problemnew/show/P2678 题目背景 一年一度的“跳石头”比赛又要开始了! 题目描述 这项比赛将在一条笔直的河道中进行,河道中分布 ...
- 【数据结构】运输计划 NOIP2015提高组D2T3
[数据结构]运输计划 NOIP2015提高组D2T3 >>>>题目 [题目描述] 公元 2044 年,人类进入了宇宙纪元.L 国有 n 个星球,还有 n−1 条双向航道,每条航 ...
- 【二分查找】 跳石头NOIP2015提高组 D2T1
[二分查找]跳石头NOIP2015提高组 D2T1 >>>>题目 [题目描述] 一年一度的“跳石头”比赛又要开始了! 这项比赛将在一条笔直的河道中进行,河道中分布着一些巨大岩石 ...
- 刷题总结——子串(NOIP2015提高组)
题目: 题目背景 NOIP2015 提高组 Day2 T2 题目描述 有两个仅包含小写英文字母的字符串 A 和 B .现在要从字符串 A 中取出 k 个互不重叠的非空子串,然后把这 k 个子串按照其在 ...
- noip2015 提高组 day1t1 神奇的幻方
题目描述 幻方是一种很神奇的N*N矩阵:它由数字1,2,3,--,N*N构成,且每行.每列及两条对角线上的数字之和都相同. 当N为奇数时,我们可以通过以下方法构建一个幻方: 首先将1写在第一行的中间. ...
- NOIP2015 提高组] 运输计划
码农题啊兄弟们. 随便考虑二分一下,然后发现要取一条满足性质的边. 被所有大于\(mid\)的路径都覆盖,取了之后能把他们都弄到小于\(mid\) 那就树上差分再处理一下. 写了\(180h\),老年 ...
- [NOIP2015 提高组] 运输计划题解
题目链接:P2680 [NOIP2015 提高组] 运输计划 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 看了好长时间题解才终于懂的,有关lca和二分答案的题解解释的不详细,一时 ...
随机推荐
- Committer 迎新!这次是来自阿里云的同学
截至今天,Apache DolphinScheduler 项目在 GitHub 上的 Star 数已突破 10.6K,贡献者人数也突破了 470 人.社区的不断壮大,离不开每位 Contributor ...
- QTreeWidget绑定QTabWidget
QTreeWidget绑定QTabWidget 本文仅供本人知识总结使用,所以内容会比较浅显,不喜勿喷. 文章目录 QTreeWidget绑定QTabWidget 一.通过treeWidget路径配合 ...
- 全网最适合入门的面向对象编程教程:39 Python常用复合数据类型-集合
全网最适合入门的面向对象编程教程:39 Python 常用复合数据类型-集合 摘要: 在 Python 中,集合(set)是一种常用的复合数据类型.集合是一组无序且不重复的元素.与列表和元组不同,集合 ...
- 阿里云图床(PicGo+阿里云OSS)搭建
阿里云图床搭建方法: 1.登录阿里云,搜索对象存储oss,新用户免费使用3个月20G,到期后,一年也就9元左右,还是很划算的. 2.在左侧列表里,点击Bucket列表,创建Bucket 3.Bucke ...
- DB\redis\zookeeper分布式锁设计
redis 参考目录: 生产级Redis 高并发分布式锁实战1:高并发分布式锁如何实现 https://www.cnblogs.com/yizhiamumu/p/16556153.html 生产级Re ...
- 用Python实现阿拉伯数字转换成中国汉字
要将阿拉伯数字转换成中国汉字表示的数字,我们需要一个映射表来转换每个数字,并且处理不同位数的数字(如十.百.千.万等). 1. Python实现阿拉伯数字转换成中国汉字 下面是一个完整的Python代 ...
- 小tips:xml文件转为html表格展示示例
books.xml文件格式如下: <?xml version="1.0" encoding="UTF-8"?> <xbrl xmlns=&qu ...
- 这款PDF解析工具,精准触达大模型问答应用的需要
过去的一年,是大语言模型快速发展的一年.大模型强大的语言理解能力,逐渐让用户习惯了将各类文章丢给大模型,让它来帮忙总结提炼.从产品角度看,这是一次10倍体验的飞跃,意味着巨大的市场机会.也因此,市面上 ...
- [OI] 模拟退火
模拟退火是一种适合求样本点较大的多峰函数极值的方法. 模拟退火有几个参数:初始温度(\(T_{0}\)),终止温度(\(T_{e}\))和降温参数 \(d\),具体地,模拟退火是让每次的当前温度 \( ...
- 第16天:信息打点-CDN绕过&业务部署&漏洞回链&接口探针&全网扫描&反向邮件
#CDN配置: 配置1:加速域名-需要启用加速的域名 配置2:加速区域-需要启用加速的地区 配置3:加速类型-需要启用加速的资源 #参考知识: 超级Ping:http://www.17ce.com/ ...