题目: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的更多相关文章

  1. 洛谷 P2593 [ZJOI2006]超级麻将【dp】

    设f[i][j][k][0/1]表示选到i时,i-1选j张,i选k张,之前选的所有牌是否选择了对子 然后分情况讨论转移即可 #include<iostream> #include<c ...

  2. [bzoj1860 ZJOI2006] 超级麻将 (线性dp)

    传送门 Description Input 第一行一个整数N(N<=100),表示玩了N次超级麻将. 接下来N行,每行100个数a1..a100,描述每次玩牌手中各种牌的数量.ai表示数字为i的 ...

  3. LUOGU 2593 : [Zjoi2006] 超级麻将

    传送门 解题思路 直接爆搜全T..状态数太多了,所以我们考虑贪心+剪枝.贪心:先拿三个连着的,再拿四个一样的,再拿三个一样的,最后拿两个一样的这样的搜索顺序最优,两个的放最后是因为只要这样的一个,三个 ...

  4. 洛谷P2507 [SCOI2008]配对 题解(dp+贪心)

    洛谷P2507 [SCOI2008]配对 题解(dp+贪心) 标签:题解 阅读体验:https://zybuluo.com/Junlier/note/1299251 链接题目地址:洛谷P2507 [S ...

  5. 洛谷 P3177 [HAOI2015]树上染色 树形DP

    洛谷 P3177 [HAOI2015]树上染色 树形DP 题目描述 有一棵点数为 \(n\) 的树,树边有边权.给你一个在 \(0 \sim n\)之内的正整数 \(k\) ,你要在这棵树中选择 \( ...

  6. 洛谷 P4072 [SDOI2016]征途 斜率优化DP

    洛谷 P4072 [SDOI2016]征途 斜率优化DP 题目描述 \(Pine\) 开始了从 \(S\) 地到 \(T\) 地的征途. 从\(S\)地到\(T\)地的路可以划分成 \(n\) 段,相 ...

  7. [ZJOI2006]超级麻将(可行性dp)

    题目描述 要判断某人是否胡牌,显然一个弱智的算法就行了,某中学信息学小组超级麻将迷想了想,决定将普通麻将改造成超级麻将. 所谓超级麻将没有了砣.索.万的区分,每种牌上的数字可以是1~100,而每种数字 ...

  8. [ZJOI2006]超级麻将

    题目描述 很多人都知道玩麻将,当然也有人不知道,呵呵,不要紧,我在这里简要地介绍一下麻将规则: 普通麻将有砣.索.万三种类型的牌,每种牌有1~9个数字,其中相同的牌每个有四张,例如1砣~9砣,1索~9 ...

  9. 洛谷P1880 石子合并(区间DP)(环形DP)

    To 洛谷.1880 石子合并 题目描述 在一个园形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分. 试设计出1 ...

随机推荐

  1. java_Set接口

    /** * Set接口:extends Collection接口 * 不重复性 * 无序 * * java.util.HashSet: * 实现Set接口,不保证set的迭代顺序,无序集合 * 底层是 ...

  2. 【学术篇】洛谷1550——打井Watering Hole

    题目の传送门:https://www.luogu.org/problem/show?pid=1550 精简版题意(本来就精简了不是么):n个点,每个点可以选择打井或从别的有水的点引水,求所有点都有水用 ...

  3. JavaScript变量名与函数名的命名规范

    JavaScrip变量名与函数名的命名规范严格遵循以下5条: (1)首字符必须是字母.下划线.$,后跟任意的字母.数字.下划线.$ (2)严格区分大小写 (3)不能使用系统的关键字和保留字 (4)命名 ...

  4. 「题解」:[BZOJ4358]permu

    问题: permu 时间限制: 30 Sec  内存限制: 512 MB 题面 题目描述 给出一个长度为n的排列P(P1,P2,...Pn),以及m个询问.每次询问某个区间[l,r]中,最长的值域 连 ...

  5. light oj 1231 dp 多重背包

    #include <stdio.h> #include <string.h> #include <stdlib.h> #include <math.h> ...

  6. iOS之CATextLayer属性简介

    1.CATextLayer简介 CATextLayer快速高效简单地来渲染纯文本.NSAttributedString /* The text layer provides simple text l ...

  7. 手势UIGestureRecognizer

    UIGestureRecognizer抽象类,六大手势是其子类: UITapGestureRecognizer      点击 UIPinchGestureRecognizer         缩放 ...

  8. 堆,栈,内存管理, 拓展补充-Geekband

    8, 堆,栈,内存管理 栈:  local objects 在离开作用域之后就会被消除.  堆: new MyClass 一直会存在 静态对象: static local object    作用域在 ...

  9. 解决mysql因内存不足导致启动报错

    报错如下所示: 解决方案: nano /etc/my.cnf 添加如下设置: key_buffer=16K table_open_cache=4 query_cache_limit=256K quer ...

  10. Ionic 列表、文本 自动 换行

    1.采用row 布局的row-warp 来处理 <div class="item item-icon-right"> <span>图片相册</span ...