[NOI2009] 管道取珠

题面很晦涩

 

直接关键部分:

最后我们所要求的 ai2 其实也就是我们得出相同的输出的方案。

这样子我们就有了基本的想法:dp

 

​但是很显然我们需要知道我们1是如何从上下两个管子里取出的,状压肯定是不行的,所以我们去推一下转移的式子,看可不可优化空间
最好想到的就是我们——  dp [i][j] [k][len]

记录下来两个人从上/下分别(其实上下可以推出来)取得球数

接下来就是喵的地方了

我们需要的状态只有 i+j==k+l 的方案

所以我们直接压吊一位

dp[l][i][j]

表示取 l 个,两个人分别从上下取 i,j 个

然后滚动数组滚掉l,这样空间就可接受了:2*500*500;

 

#include<bits/stdc++.h>

using namespace std;
const int N=504;
const int mod=1024523;

int n,m;

char s1[N],s2[N];
int dp[5][N][N];

int main()
{
    ios::sync_with_stdio(false);
    cin>>n>>m;
    
    cin>>s1+1>>s2+1;
    
    dp[0][0][0]=1;
    
    for(int i=0;i<=n;i++)
    {
        int x=i&1;
        int pre=x^1;
        
        memset(dp[pre],0,sizeof(dp[pre]));
        

            for(int j=0;j<=m;j++)
            {
                for(int k=0;k<=i+j;k++)
                {
                int len=i+j-k;
                if(s1[i+1]==s1[k+1]) 
                (dp[x^1][j][k+1]+=dp[x][j][k])%=mod;
                
                if(s1[i+1]==s2[len+1]) 
                (dp[x^1][j][k]+=dp[x][j][k])%=mod;
                if(s2[j+1]==s1[k+1]) 
                (dp[x][j+1][k+1]+=dp[x][j][k])%=mod;
                
                if(s2[j+1]==s2[len+1])
                (dp[x][j+1][k]+=dp[x][j][k])%=mod;
                        
                }
            }
        
    }
    cout<<dp[n&1][m][n];
    return 0;
}

 

posted @ 2021-08-19 14:11  Hehe_0  阅读(48)  评论(0)    收藏  举报