洛谷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 ...
随机推荐
- Ubuntu环境下java.lang.SecurityException: Invalid signature file digest for Manifest main attributes
一.问题描述 Ubuntu环境中,将maven项目打包成jar包传到服务器中后运行以下指令: $ java -cp my.jar com.myproject.Main 遇到报错: java.lang. ...
- JS规则 自加一,自减一 ( ++和- -) 【mynum = mynum + 1;//等同于mynum++;】
自加一,自减一 ( ++和- -) 算术操作符除了(+.-.*./)外,还有两个非常常用的操作符,自加一"++":自减一"--".首先来看一个例子: mynum ...
- Vue项目在Docker的自动化部署
操作系统:CentOS 部署环境:Docker CI/CD工具:Jenkins 1.环境配置 安装Jenkins:Centos安装Jenkins 安装Docker:Centos安装Git.DotNet ...
- rsyslog 服务器重启后 发现不能接受到外部日志 只能接受本地日志 关闭防火墙即可
rsyslog 服务器重启后 发现不能接受到外部日志 只能接受本地日志 关闭防火墙即可 1 关闭防火墙: # systemctl stop firewalld 2 将SELINUX设置为disabl ...
- 07.07NOIP模拟赛
考中 考试时不知道自己在想啥.. 拿到第一题:woc组合数学,第二题:woc组合数学,第三题,woc组合数学. 然后开始认真读题…… 我tm真是闲的... 第一题是15年山东省选题,感觉暴力搜索都没法 ...
- /usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crt1.o:在函数‘_start’中: (.text+0x20):对‘main’未定义的引用
原因是新建了一个可执行的函数,里面却没有main函数,加上main函数即可
- python随机数(转载)
随机生成 0 到 1 之间的浮点数 random.random() 方法会返回 [0.0, 1.0) 之间的浮点数,注意,这是一个左闭右开的区间,随机数可能会是 0 但不可能为 1 . 随机生成 a ...
- 微信小程序连续旋转动画this.animation.rotate
一..js中封装旋转动画方法 添加animation属性 data:{ animation:''" } 改变animation的值(官网提供角度范围是-180~180,但是我发现角度越大会一 ...
- IT技术博客
博客收藏大全: 陈皓博客: 陈硕的博客: 风云的博客: 当然我在扯淡: hellogirl: 田守枝Java技术博客: 廖雪峰博客: Milo游戏开发:
- java基础之Calender类
Calendar: Calendar类概述 Calendar 类是一个抽象类,它为特定瞬间与一组诸如 YEAR.MONTH.DAY_OF_MONTH.HOUR 等 日历字段之间的转换提供了一些方法,并 ...