[NOI 2009] bzoj1566 管道取珠 [dp]

Description:
有兩種珠子,有兩個管道,每個管道里有一些珠子,每次可以從上面或下面取珠子構成序列,問構成相同序列的操作對數。


Solution:
考慮dp[len][i][j] 表示當前取了len 個珠子,第一個操作從上面取了i 個,第二個操作從上面取了j 個且構成序列相同的方案數,dp 即可。
這類題的套路是把平方轉化爲對數進行統計。


#include <bits/stdc++.h>
using namespace std;
const int maxn = 505;
int n, m;
int dp[2][maxn][maxn];
char s[maxn], t[maxn];
void u(int &x, int y) {
    x = (x + y) % 1024523;
}
int main() {
    scanf("%d%d%s%s", &n, &m, s + 1, t + 1);
    reverse(s + 1, s + n + 1);
    reverse(t + 1, t + m + 1);
    dp[0][0][0] = 1;
    for(int N = 0, pre = 0; N < n + m; ++N, pre ^= 1) {
        memset(dp[pre ^ 1], 0, sizeof(dp[pre ^ 1])); 
        for(int i = 0; i <= N && i <= n; ++i) {
            for(int j = 0; j <= N && j <= n; ++j) {
                if(s[i + 1] == s[j + 1]) {
                    u(dp[pre ^ 1][i + 1][j + 1], dp[pre][i][j]);
                }
                if(s[i + 1] == t[N - j + 1]) {
                    u(dp[pre ^ 1][i + 1][j], dp[pre][i][j]);
                }
                if(t[N - i + 1] == s[j + 1]) {
                    u(dp[pre ^ 1][i][j + 1], dp[pre][i][j]);
                }
                if(t[N - i + 1] == t[N - j + 1]) {
                    u(dp[pre ^ 1][i][j], dp[pre][i][j]);
                }
            }
        }
    }
    printf("%d\n", dp[(n + m) & 1][n][n]);
    return 0;
}
發佈了102 篇原創文章 · 獲贊 1 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章