洛谷2593 [ZJOI2006]超级麻将——可行性dp
题目:https://www.luogu.org/problemnew/show/P2593
发现三个连续牌的影响范围只有3、相同牌的影响范围只有1之后就可以dp了。
O(100^7)T飞。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=;
int T,a[N];
bool dp[][N][N][N],flag;
int rdn()
{
int ret=;char ch=getchar();
while(ch>''||ch<'')ch=getchar();
while(ch>=''&&ch<='')(ret*=)+=ch-'',ch=getchar();
return ret;
}
int main()
{
T=rdn();
while(T--)
{
for(int i=;i<=;i++)a[i]=rdn();
for(int t=;t<=;t++)if(a[t]>=)
{
a[t]-=;
memset(dp[],,sizeof dp[]);
dp[][a[]][a[]][a[]]=;
for(int i=;i<=;i++)
{
flag=;int d=(i&);
memset(dp[!d],,sizeof dp[!d]);
for(int x=;x<=a[i-];x++)
for(int y=;y<=a[i-];y++)
for(int z=;z<=a[i];z++)
if(dp[d][x][y][z])
{
int lm=min(x,min(y,z));
for(int k=;k<=lm;k++)
{
dp[!d][y-k][z-k][a[i+]]|=(((x-k)%==)|((x-k)%==));
if(dp[!d][y-k][z-k][a[i+]])flag=;
}
}
if(!flag)break;
}
a[t]+=;
if(flag)break;
}
if(flag)printf("Yes\n");else printf("No\n");
}
return ;
}
如果不枚举对子在哪而是带一个0/1在状态里的话可以少乘一个100。
如果不无脑记录前两个位置而是仅记录前一个位置、用三连的时候调用一下上一层的话可以少乘一个100。
这是因为最后要的只有dp[ ][0][0][0],所以保存很多“之前位置还不是0”的状态比较浪费。
不枚举用了几个三连,而是每层用“从开头降到这里”更新一下本层,就能把”在本层用较少的三连“包括在“用单个位置从之前层降下来”。这样可以少乘一个100。
这里调了好久!必须是“从开头降到这里”,而不能是“从这里降到0”;因为从“这里”降的话需要判断本层是否可行,但这个可行是包括 i-2 的状态的,自己仅记录前一个位置的dp不能存下。如果是”从开头降到这里“的话,本层目前一定是可行的。
O(100^4)卡过。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=;
int T,a[N];
bool dp[N][N][N][];
int rdn()
{
int ret=;char ch=getchar();
while(ch>''||ch<'')ch=getchar();
while(ch>=''&&ch<='')(ret*=)+=ch-'',ch=getchar();
return ret;
}
int main()
{
T=rdn();
while(T--)
{
memset(dp,,sizeof dp);
for(int i=;i<=;i++)a[i]=rdn();
dp[][][a[]][]=;
for(int i=;i<=;i++)
{
for(int x=a[i-];x>=;x--)
for(int y=a[i];y>=;y--)
{
dp[i][x][y][]|=dp[i][x][y+][]; dp[i][x][y][]|=dp[i][x][y+][];
dp[i][x][y][]|=dp[i][x][y+][]; dp[i][x][y][]|=dp[i][x][y+][];
dp[i][x][y][]|=dp[i][x][y+][];
//在a[i]变成各种y之后尝试一下从开头降到这里(先降后单个弄)
dp[i][x][y][]|=dp[i-][a[i]-y][x+a[i]-y][];
dp[i][x][y][]|=dp[i-][a[i]-y][x+a[i]-y][]; //在a[i]变成各种y之后尝试一下取完
// dp[i][x][0][0]|=dp[i-1][y][x+y][0];//不能&dp[i][x+y][y],因含义是i-2==0
// dp[i][x][0][1]|=dp[i-1][y][x+y][1];//不&的话会出错:0 3 0(原为2)
//因为从当前降到0的话,需要判断当前是否可行
//可是降还需要i-2的也许有值,与表示“当前可行”的dp冲突,即无法表示当前是否可行
//而“从开头”降的话,一定可行 //x之所以不是0,是因为这里用到dp[i-1][y][][]
if(!x)
{
dp[i+][y][a[i+]][]|=dp[i][][y][];
dp[i+][y][a[i+]][]|=dp[i][][y][];
}
// if(i<=3)
// {
// if(dp[i][x][y][0])printf("dp[%d][%d][%d][%d]=%d\n",i,x,y,0,dp[i][x][y][0]);
// if(dp[i][x][y][1])printf("dp[%d][%d][%d][%d]=%d\n",i,x,y,1,dp[i][x][y][1]);
// }
}
}
puts(dp[][][][]?"Yes":"No");
}
return ;
}
洛谷2593 [ZJOI2006]超级麻将——可行性dp的更多相关文章
- 洛谷 P2593 [ZJOI2006]超级麻将【dp】
设f[i][j][k][0/1]表示选到i时,i-1选j张,i选k张,之前选的所有牌是否选择了对子 然后分情况讨论转移即可 #include<iostream> #include<c ...
- [bzoj1860 ZJOI2006] 超级麻将 (线性dp)
传送门 Description Input 第一行一个整数N(N<=100),表示玩了N次超级麻将. 接下来N行,每行100个数a1..a100,描述每次玩牌手中各种牌的数量.ai表示数字为i的 ...
- LUOGU 2593 : [Zjoi2006] 超级麻将
传送门 解题思路 直接爆搜全T..状态数太多了,所以我们考虑贪心+剪枝.贪心:先拿三个连着的,再拿四个一样的,再拿三个一样的,最后拿两个一样的这样的搜索顺序最优,两个的放最后是因为只要这样的一个,三个 ...
- 洛谷P2507 [SCOI2008]配对 题解(dp+贪心)
洛谷P2507 [SCOI2008]配对 题解(dp+贪心) 标签:题解 阅读体验:https://zybuluo.com/Junlier/note/1299251 链接题目地址:洛谷P2507 [S ...
- 洛谷 P3177 [HAOI2015]树上染色 树形DP
洛谷 P3177 [HAOI2015]树上染色 树形DP 题目描述 有一棵点数为 \(n\) 的树,树边有边权.给你一个在 \(0 \sim n\)之内的正整数 \(k\) ,你要在这棵树中选择 \( ...
- 洛谷 P4072 [SDOI2016]征途 斜率优化DP
洛谷 P4072 [SDOI2016]征途 斜率优化DP 题目描述 \(Pine\) 开始了从 \(S\) 地到 \(T\) 地的征途. 从\(S\)地到\(T\)地的路可以划分成 \(n\) 段,相 ...
- [ZJOI2006]超级麻将(可行性dp)
题目描述 要判断某人是否胡牌,显然一个弱智的算法就行了,某中学信息学小组超级麻将迷想了想,决定将普通麻将改造成超级麻将. 所谓超级麻将没有了砣.索.万的区分,每种牌上的数字可以是1~100,而每种数字 ...
- [ZJOI2006]超级麻将
题目描述 很多人都知道玩麻将,当然也有人不知道,呵呵,不要紧,我在这里简要地介绍一下麻将规则: 普通麻将有砣.索.万三种类型的牌,每种牌有1~9个数字,其中相同的牌每个有四张,例如1砣~9砣,1索~9 ...
- 洛谷P1880 石子合并(区间DP)(环形DP)
To 洛谷.1880 石子合并 题目描述 在一个园形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分. 试设计出1 ...
随机推荐
- js 实现纵向轮播
效果 html <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <t ...
- js字符实体 转义字符串
HTML字符实体(Character Entities),转义字符串(Escape Sequence) 为什么要用转义字符串? HTML中<,>,&等有特殊含义(<,> ...
- .Global.asax.cs中的方法的含义
Application_Init:在每一个HttpApplication实例初始化的时候执行 Application_Disposed:在每一个HttpApplication实例被销毁之前执行 App ...
- [转]Java四种线程池的使用
Java通过Executors提供四种线程池,分别为:newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程.newFixe ...
- python所有的标准异常类
异常名称 描述 BaseException 所有异常的基类 SystemExit 解释器请求退出 KeyboardInterrupt 用户中断执行(通常是输入^C) Exception 常规错误的基类 ...
- Docker配置JDK1.8
1.安装Docker(菜鸟教程有) https://www.runoob.com/docker/centos-docker-install.html 2.docker下载centos镜像(用作配置jd ...
- 来杭州云栖大会,全面了解企业如何实现云上IT治理
企业上云的现状与趋势 云计算,如今已经成为了像水和电一般关系到国计民生的国家基础设施.云计算为企业带了前所未有的资源交付效率和运维效率的提升,同时也用全新的技术帮助企业在新的价值网络中创造新的商业赛道 ...
- DRF 序列化组件单增
目录 自定义序列化(矬) Serializer类(方式繁琐) 底层序列化类 UserSerializer 视图序列化步骤 底层反序列化类 UserCreatSerializer 视图反序列化步骤 Mo ...
- ConcurrentHashMap 和 Hashtable 的区别
ConcurrentHashMap 和 Hashtable 的区别主要体现在实现线程安全的方式上不同. 1.底层的数据结构: ConcurrentHashMap 在jdk1.7之前采用的是 分段的数组 ...
- Zuul微服务网关
Zuul简介: Zuul是Netflix开源的微服务网关,它可以和Eureka.Ribbon.Hystrix等组件配合使用.Zuul的核心是一系列的过滤器,这些过滤器可以完成以下功能 ...