zoukankan      html  css  js  c++  java
  • Codeforces 682D Alyona and Strings(DP)

    题目大概说给两个字符串s和t,然后要求一个包含k个字符串的序列,而这个序列是两个字符串的公共子序列,问这个序列包含的字符串的总长最多是多少。

    如果用DP解,考虑到问题的规模,自然这么表示状态:

    • dp[i][j][k]表示s[0...i]与t[0...j]包含k个字符串的公共子序列的最大总长

    想怎么转移时,我发现这样表示状态不好转移,还得加一维:

    • dp[i][j][k][0]表示s[0...i]与t[0...j]包含k个字符串的公共子序列的最大总长,且s[i]和t[j]不属于序列第k个字符串
    • dp[i][j][k][1]表示s[0...i]与t[0...j]包含k个字符串的公共子序列的最大总长,且s[i]和t[j]属于序列第k个字符串

    转移的话:

    • dp[i][j][k][1]能转移仅s[i]=t[j],可以通过在s[0...i-1]和t[0...j-1]的后面作为新加的序列字符串转移,即d[i-1][j-1][k-1]+1;也可以不作为新加的序列字符串,与前面的拼接转移,不过仅当s[i-1]=t[j-1],即dp[i-1][j-1][k]+1;
    • dp[i][j][k][0]就是s[i]、t[j]忽略的情况,从dp[i-1][j][k]、dp[i][j-1][k]和dp[i][j][k]转移

    转移感觉很麻烦,写着写着调着调着,终于过了样例,然后直接提交——居然就AC了?简直不敢相信。。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 int d[1111][1111][11][2];
     6 int main(){
     7     int n,m,K;
     8     char s[1111]={0},t[1111]={0};
     9     scanf("%d%d%d",&n,&m,&K);
    10     for(int i=0; i<n; ++i){
    11         scanf(" %c",&s[i]);
    12     }
    13     for(int i=0; i<m; ++i){
    14         scanf(" %c",&t[i]);
    15     }
    16     memset(d,0,sizeof(d));
    17     if(s[0]==t[0]) d[0][0][1][1]=1;
    18     for(int i=0; i<n; ++i){
    19         for(int j=0; j<m; ++j){
    20             if(i==0 && j==0) continue;
    21             for(int k=1; k<=K; ++k){
    22                 if(i==0){
    23                     if(s[i]==t[j]){
    24                         d[i][j][1][1]=1;
    25                     }
    26                     d[i][j][1][0]=max(d[i][j-1][1][0],d[i][j-1][1][1]);
    27                 }else if(j==0){
    28                     if(s[i]==t[j]){
    29                         d[i][j][1][1]=1;
    30                     }
    31                     d[i][j][1][0]=max(d[i-1][j][1][0],d[i-1][j][1][1]);
    32                 }else{
    33                     if(s[i]==t[j]){
    34                         d[i][j][k][1]=max(d[i-1][j-1][k-1][0],d[i-1][j-1][k-1][1])+1;
    35                         if(s[i-1]==t[j-1]) d[i][j][k][1]=max(d[i][j][k][1],d[i-1][j-1][k][1]+1);
    36                     }
    37                     d[i][j][k][0]=max(d[i-1][j][k][0],d[i][j-1][k][0]);
    38                     d[i][j][k][0]=max(d[i][j][k][0],d[i][j-1][k][1]);
    39                     d[i][j][k][0]=max(d[i][j][k][0],d[i-1][j][k][1]);
    40                     d[i][j][k][0]=max(d[i][j][k][0],d[i-1][j-1][k][0]);
    41                     if(s[i-1]==t[j-1]) d[i][j][k][0]=max(d[i][j][k][0],d[i-1][j-1][k][1]);
    42                 }
    43             }
    44         }
    45     }
    46     printf("%d",max(d[n-1][m-1][K][0],d[n-1][m-1][K][1]));
    47     return 0;
    48 }
  • 相关阅读:
    汇编(一)续
    汇编(一)
    Ubuntu 安装配置Dosbox
    Linux系统安装Dos系统(虚拟机里装)
    .bundle文件如何安装
    Linux(Fedora)系统下配制8086汇编环境
    Linux常用命令
    linux下安装nginx
    缓存雪崩、缓存穿透、缓存击穿是什么?如何解决?
    Maven 实战
  • 原文地址:https://www.cnblogs.com/WABoss/p/5662353.html
Copyright © 2011-2022 走看看