zoukankan      html  css  js  c++  java
  • UVA 10739 String to Palindrome(动态规划 回文)

    String to Palindrome

    题目大意:给出一个字符串s,现在可以进行3种操作(添加字母,删除字母,替换字母),将其变成回文串,求出最少的操作次数。比如abccda,可以用删除操作,删除b,d两步可变成回文;但如果用替换操作,把b换成d则只需要1步。

    分析:刚开始我一直考虑它是否具有最优子结构性质,直到现在,还是不明白为什么可以用动态规划来做,大神若是看见,还望指教。

      由于添加字母和删除字母的效果是一样的,因此我们这里就只进行删除和替换操作。令dp[i][j]表示从第 i 到第 j 个字母变成回文所需要最少的操作数。

      转移方程为:当是s[i]==s[j]时,dp[i][j] = dp[i+1][j-1];此外dp[i][j] = min(dp[i+1][j],dp[i+1][j-1],dp[i][j-1]) + 1;  dp[i+1][j-1]+1 是替换操作,其他两种是删除操作。

      初始条件是:j<=i 时dp[i][j] = 0; 如果只是单一的字母,它本身就是回文

    递推代码如下:

     1 # include<cstdio>
     2 # include<cstring>
     3 # include<iostream>
     4 using namespace std;
     5 char s[1005];
     6 int dp[1005][1005];
     7 int main()
     8 {
     9     int T,cas;
    10     scanf("%d",&T);
    11     for(cas=1; cas<=T; cas++)
    12     {
    13         scanf("%s",s);
    14         int len =strlen(s);
    15         int i,j;
    16         for(i=0; i<len; i++)
    17                 dp[i][i] = 0;
    18         for(i=len-1; i>=0; i--)
    19             for(j=i+1; j<len; j++)
    20             {
    21                 if(s[i]==s[j])
    22                     dp[i][j] = dp[i+1][j-1];
    23                 else
    24                     dp[i][j] = min(min(dp[i+1][j],dp[i+1][j-1]),dp[i][j-1])+1;
    25             }
    26         printf("Case %d: %d
    ",cas,dp[0][len-1]);
    27     }
    28     return 0;
    29 }

    递归代码如下:

     1 # include<cstdio>
     2 # include<cstring>
     3 # include<iostream>
     4 using namespace std;
     5 char s[1005];
     6 int dp[1005][1005];
     7 int DP(int x,int y){
     8     if(dp[x][y] != -1)
     9         return dp[x][y];
    10     if(y <= x )
    11         return dp[x][y] = 0;
    12     if(s[x] == s[y])
    13         dp[x][y] = DP(x+1,y-1);
    14     else
    15         dp[x][y] = min( min(DP(x+1,y),DP(x+1,y-1)),(DP(x,y-1))) + 1;
    16         return dp[x][y];
    17 }
    18 int main(){
    19     int T,cas;
    20     scanf("%d",&T);
    21     for(cas=1;cas<=T;cas++){
    22         scanf("%s",s);
    23         int len =strlen(s);
    24         memset(dp,-1,sizeof(dp));
    25         printf("Case %d: %d
    ",cas,DP(0,len-1));
    26     }
    27     return 0;
    28 }
  • 相关阅读:
    XJ20夏令营做题记录(长期更新)
    洛谷P6623——[省选联考 2020 A 卷] 树
    [游记] 2020ZJOI 爆零记
    CF1017G——The Tree
    CF715E—— Complete the Permutations
    学习笔记——树的初步整理
    学习笔记——DP初步整理
    洛谷P5290——春节十二响
    POJ3017——Cut the Sequence(单调队列+堆优化DP)
    Java控制整形输入的法子
  • 原文地址:https://www.cnblogs.com/acm-bingzi/p/3217692.html
Copyright © 2011-2022 走看看