现在的位置: 首页 > 综合 > 正文

zoj 1642 Match for Bonus[dp,lcs]

2017年05月28日 ⁄ 综合 ⁄ 共 999字 ⁄ 字号 评论关闭

题目链接:点击打开链接

 最长公共子序列。每一个字符都有一个权重。小小改一下就好。

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <map>
using namespace std;

const int N = 2005;
int dp[N][N];
map<char, int> M;
int lcs(char *s1, char *s2){
    int len1 = strlen(s1), len2 = strlen(s2);
    memset(dp, 0, sizeof(dp));
    for(int i = 1; i <= len1; i ++){
        for(int j = 1; j <= len2; j ++)
        if(s1[i - 1] == s2[j - 1]) dp[i][j] = dp[i - 1][j - 1] + M[s1[i - 1]];
        else dp[i][j] = max(dp[i][j - 1], dp[i - 1][j]);
    }
    return dp[len1][len2];
}

int main(){
    int n;
    while(~scanf("%d", &n)){
        char c;
        int d;
        for(int i = 1; i <= n; i ++){
            getchar();
            scanf("%c %d", &c, &d);
            M[c] = d;
        }
        char str1[N], str2[N];
        scanf("%s %s", str1, str2);
        printf("%d\n",lcs(str1, str2));
    }
    return 0;
}

最长公共子序列很的简单,但是很久都没有接触过dp了。还是需要全面的发展的。

dp[i][j] 代表第一个序列的前i个元素和第二个序列的前j个元素最长公共子序列。

如果第一个序列的第i个元素和第二个序列的第j个元素相同,那么dp[i][j] = dp[i - 1][j - 1] + 1,也就是说第一个序列的前i个元素和第二个序列的前j个元素的最长公共子序列为第一个序列的前i - 1个元素和第二个序列的前j - 1个元素的最长公共子序列+1。

如果不同,第一个序列的前i个元素和第二个序列的前j个元素的最长公共子序列为第一个序列的前i - 1个元素和第二个序列的前j个元素的最长公共子序列和第一个序列的前i个元素和第二个序列的前j - 1个元素的最长公共子序列中的较大者。为最优解。

那么对于这道题来说,只不过是对于每一个字符加了一个权重而已。每次增加的不在是1,而是相同字符的权重。

dp也要搞。慢慢来。

抱歉!评论已关闭.