博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
TJOI2018Party
阅读量:6113 次
发布时间:2019-06-21

本文共 1560 字,大约阅读时间需要 5 分钟。

题目描述

小豆参加了\(NOI\)的游园会,会场上每完成一个项目就会获得一个奖章,奖章 只会是\(N\), \(O\), \(I\)的字样。在会场上他收集到了\(K\)个奖章组成的串。

兑奖规则是奖章串和兑奖串的最长公共子序列长度为小豆最后奖励的等级。

现在已知兑奖串长度为\(N\),并且在兑奖串上不会出现连续三个奖章为\(NOI\),即奖章中不会出现子串\(NOI\)

现在小豆想知道各个奖励等级会对应多少个不同的合法兑奖串。

题解

我们可以先考忽略那些奇奇怪怪的限制条件,直接考虑如何统计序列数。

我们先考虑\(LCS\)的dp方法。

\[ dp[i][j]=max(dp[i-1][j],dp[i][j-1],dp[i-1][j-1]+(s[i]==t[j])) \]
我们如果把第二维单独拿出来考虑,我们可以发现第二维是一个单调不降的数列而且前后两项的差是小于等于1的。

因为第二维的长度非常小,所以我们可以把第二维差分之后状压起来作为我们的状态。

而且有一个好处,我们知道了这个状态,就能发当前\(dp\)值还原出来,假设我们知道了下一个字符时什么,我们就可以知道转移后的状态是什么了。

所以我们预处理\(g[i][j]\)表示当前状态为\(i\),新加入字符为\(j\),能够转移的状态。

然后我们再设\(dp[i][j][k]\)表示做到第\(i\)为,当前状态为\(j\),匹配到k个字符(这个是判断那个特殊限制用的),随便转移一下就好了。

代码

#include
#include
#include
using namespace std;const int mod=1e9+7;int tran[200],g[3][1<<16],dp[2][1<<16][3],n,k,nw[20],a[20],ma,ans[20];char s[20];inline int rd(){ int x=0;char c=getchar();bool f=0; while(!isdigit(c)){if(c=='-')f=1;c=getchar();} while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();} return f?-x:x;}inline void MOD(int &x){x=x>=mod?x-mod:x;}int main(){ n=rd();k=rd(); tran['N']=0;tran['O']=1;tran['I']=2; scanf("%s",s+1); for(int i=1;i<=k;++i)a[i]=tran[(int)s[i]]; ma=(1<
=1;--j){ nw[j]=max(nw[j],nw[j-1]); if(a[j]==o)nw[j]=max(nw[j],nw[j-1]+1); } for(int j=1;j<=k;++j)nw[j]=max(nw[j],nw[j-1]); int s=0; for(int j=k;j>=1;--j)nw[j]=nw[j]-nw[j-1]; for(int j=0;j<=k;++j)s|=(1<

转载于:https://www.cnblogs.com/ZH-comld/p/10554475.html

你可能感兴趣的文章
PHP经典算法题
查看>>
LeetCode 404 Sum of Left Leaves
查看>>
醋泡大蒜有什么功效
查看>>
hdu 5115(2014北京—dp)
查看>>
数据结构中常见的树(BST二叉搜索树、AVL平衡二叉树、RBT红黑树、B-树、B+树、B*树)...
查看>>
PHP读取日志里数据方法理解
查看>>
第五十七篇、AVAssetReader和AVAssetWrite 对视频进行编码
查看>>
Vivado增量式编译
查看>>
一个很好的幻灯片效果的jquery插件--kinMaxShow
查看>>
微信支付签名配置正确,但返回-1,调不出支付界面(有的手机能调起,有的不能)...
查看>>
第二周例行报告
查看>>
多线程条件
查看>>
黄聪:VMware安装Ubuntu10.10【图解】转
查看>>
Centos 6.x 升级openssh版本
查看>>
公式推♂倒题
查看>>
vue实现点击展开,点击收起
查看>>
如何使frame能居中显示
查看>>
第k小数
查看>>
构建之法阅读笔记三
查看>>
写给对前途迷茫的朋友:五句话定会改变你的人生
查看>>