zoukankan      html  css  js  c++  java
  • P1758-[NOI2009]管道取珠【dp】

    正题

    题目链接:https://www.luogu.com.cn/problem/P1758


    题目大意

    给出一个大小为(n)和一个大小为(m)的栈,每次选择一个栈弹出栈顶然后记录这个字母,求所有弹出序列的弹出方案的二次方和。

    (1leq n,mleq 500)


    解题思路

    二次方和可以看为取出方案相同的对数。

    然后就是很简单的(dp)了,设(f_{i,j,k})表示都取出了(i)个,在第一个栈里分开取了(j/k)个,然后滚动。

    时间复杂度(O(nmn^2))


    code

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N=510,P=1024523;
    int n,m,f[N*2][N][N];
    char s[N],t[N];
    int main()
    {
    	scanf("%d%d",&n,&m);
    	scanf("%s",s+1);
    	scanf("%s",t+1);
    	f[0][0][0]=1;
    	for(int i=1;i<=n+m;i++)
    		for(int j=0;j<=min(n,i);j++)
    			for(int k=0;k<=min(n,i);k++){
    				f[i&1][j][k]=0;
    				if(s[j]==s[k]&&j&&k)(f[i&1][j][k]+=f[~i&1][j-1][k-1])%=P;
    				if(s[j]==t[i-k]&&j&&i-k)(f[i&1][j][k]+=f[~i&1][j-1][k])%=P;
    				if(t[i-j]==s[k]&&k&&i-j)(f[i&1][j][k]+=f[~i&1][j][k-1])%=P;
    				if(t[i-j]==t[i-k]&&i-j&&i-k)(f[i&1][j][k]+=f[~i&1][j][k])%=P;
    			}
    	printf("%d
    ",f[(n+m)&1][n][n]);
    	return 0;
    }
    
  • 相关阅读:
    人生本来就是一种修行
    Go的一些趣味题库
    PHP系统常被挂马的代码
    PHP加密字符串函数(解密)
    photoshop
    截图
    用手机作为摄像头
    IM 学习记录
    编译 学习过程
    过程流水记录-编译Lua srlua使用iup-完结
  • 原文地址:https://www.cnblogs.com/QuantAsk/p/15136728.html
Copyright © 2011-2022 走看看