zoukankan      html  css  js  c++  java
  • 【BZOJ1566】管道取珠(NOI2009)-DP+问题转化

    测试地址:管道取珠
    做法:本题需要用到DP+问题转化。
    这道题最妙的地方在于对问题的转化。考虑ai2的组合意义,我们发现它等价于玩两次游戏,得到的输出序列相同的方案数,那么我们令dp(i,j,k)为前i轮中,第一次游戏取了上管道的前j个珠子,第二次游戏取了上管道的前k个珠子,得到的输出序列相同的方案数,那么状态转移方程就很好写了,时间复杂度为O(n3)
    这题时限卡得有点紧,需要加一些玄学的优化,详见代码。
    测试地址:

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const ll mod=1024523;
    int n,m;
    ll dp[2][510][510]={0};
    char A[510],B[510];
    
    int main()
    {
        scanf("%d%d",&n,&m);
        scanf("%s%s",A,B);
        for(int i=0;i<n-i-1;i++)
            swap(A[i],A[n-i-1]);
        for(int i=0;i<m-i-1;i++)
            swap(B[i],B[m-i-1]);
    
        int now=1,past=0;
        dp[past][0][0]=1;
        for(int i=1;i<=n+m;i++)
        {
            memset(dp[now],0,sizeof(dp[now]));
            for(int j=max(0,i-m-1);j<=n;j++)
                for(int k=max(0,i-m-1);k<=n;k++)
                    if (dp[past][j][k])
                    {
                        if (j<n&&k<n&&A[j]==A[k]) dp[now][j+1][k+1]=(dp[now][j+1][k+1]+dp[past][j][k])%mod;
                        if (j<n&&i-k<=m&&A[j]==B[i-k-1]) dp[now][j+1][k]=(dp[now][j+1][k]+dp[past][j][k])%mod;
                        if (i-j<=m&&k<n&&B[i-j-1]==A[k]) dp[now][j][k+1]=(dp[now][j][k+1]+dp[past][j][k])%mod;
                        if (i-j<=m&&i-k<=m&&B[i-j-1]==B[i-k-1]) dp[now][j][k]=(dp[now][j][k]+dp[past][j][k])%mod;
                    }
            swap(now,past);
        }
        printf("%lld",dp[past][n][n]);
    
        return 0;
    }
  • 相关阅读:
    练习44-继承和组合
    CF 1329B Dreamoon Likes Sequences
    CF 1362C Johnny and Another Rating Drop
    CF 1391D 505
    CF 1383B GameGame
    CF1360F Spy-string(暴力)
    Java 之 关键字与标识符
    Java 之 Java 注释与 API
    Java 之 第一个Java程序
    Java 之 Java开发环境
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793397.html
Copyright © 2011-2022 走看看