UOJ#748-[UNR #6]机器人表演【dp】

1|0正题

题目链接:https://uoj.ac/problem/748


1|1题目大意

有一个长度为n01序列,然后t次插入一个0和一个1,要求01前面,求最终能得到多少种本质不同的串。

1n,t300


1|2解题思路

我们考虑一个n+2×t01串是否合法,而且我们最好能搞出一种记录信息最少且唯一的方法。

我们记录一个x表示当前匹配到的位置,当我们加入一个01时,如果恰好能和下一个匹配,我们就匹配。否则如果是0,我们再记录一个y表示目前有多少个未匹配的0。如果是1,如果前面有未匹配的0,我们就用未匹配的0和这个1匹配。

如果没有我们就一直让匹配位置x往前走,直到出现一个未匹配的0,我们可以先预处理出一个pi表示匹配位置i往前跳到出现第一个未匹配0的位置。

这种匹配方法一定是最优的,因为往前跳一到的位置一定是一个0,而之后我们拿未匹配的0去匹配这个0显然不优秀。

然后我们设fi,j,k表示现在填到第i个,目前匹配到位置j,前面有k个未匹配的0时前面填的方案数转移即可。

时间复杂度:O(n3)


1|3code

#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=305,P=998244353; int n,t,f[N*3][N][N],pre[N]; char s[N]; void Add(int &x,int y) {x=(x+y>=P)?(x+y-P):(x+y);} int main() { // printf("%d\n",sizeof(f)>>20); scanf("%d%d",&n,&t); scanf("%s",s+1);pre[0]=-1; for(int i=1;i<=n;i++){ int p=0; for(int j=i;j>=1;j--){ if(s[j]=='1')p++; else p--; if(p==-1){pre[i]=j-1;break;} } if(p!=-1)pre[i]=-1; } f[0][0][0]=1; for(int i=0;i<n+2*t;i++) for(int j=0;j<=n;j++) for(int k=0;k<=t;k++){ if(!f[i][j][k])continue; //zero if(s[j+1]=='0')Add(f[i+1][j+1][k],f[i][j][k]); else Add(f[i+1][j][k+1],f[i][j][k]); //one if(s[j+1]=='1')Add(f[i+1][j+1][k],f[i][j][k]); else{ if(k)Add(f[i+1][j][k-1],f[i][j][k]); else if(pre[j]!=-1)Add(f[i+1][pre[j]][k],f[i][j][k]); } } printf("%d\n",f[n+2*t][n][0]); return 0; }

__EOF__

本文作者QuantAsk
本文链接https://www.cnblogs.com/QuantAsk/p/16561159.html
关于博主:退役OIer,GD划水选手
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   QuantAsk  阅读(205)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
历史上的今天:
2021-08-08 P4233-射命丸文的笔记【NTT,多项式求逆】
2021-08-08 bzoj#4722-由乃【倍增,抽屉原理,bitset】
2021-08-08 CF835E-The penguin‘s game【交互】
2021-08-08 bzoj#4423-[AMPPZ2013]Bytehattan【并查集】
2021-08-08 P4780-Phi的反函数【dfs】
点击右上角即可分享
微信分享提示