zoukankan      html  css  js  c++  java
  • 二维动态规划——Palindrome

    Palindrome
    Description
    A palindrome is a symmetrical string, that is, a string read identically from left to right as well as from right to left. You are to write a program which, given a string, determines the minimal number of characters to be inserted into the string in order to obtain a palindrome.
    As an example, by inserting 2 characters, the string "Ab3bd" can be transformed into a palindrome ("dAb3bAd" or "Adb3bdA"). However, inserting fewer than 2 characters does not produce a palindrome.

    Input
    Your program is to read from standard input. The first line contains one integer: the length of the input string N, 3 <= N <= 5000. The second line contains one string with length N. The string is formed from uppercase letters from 'A' to 'Z', lowercase letters from 'a' to 'z' and digits from '0' to '9'. Uppercase and lowercase letters are to be considered distinct.

    Output
    Your program is to write to standard output. The first line contains one integer, which is the desired minimal number.

    Sample Input
    5
    Ab3bd

    Sample Output
    2

    状态转移方程为dp[i][j] = {min(dp[i + 1][j], dp[i][j - 1]) + 1 | str[i] != str[j], dp[i + 1][j - 1] | str[i] = str[j]},代码如下,注意其中的递归起始点是如何得到的(我们从最最边界的位置开始),空间复杂度可用滚动数组优化到O(n)。

    #include <cstring>
    #include <algorithm>
    #include <iostream>
    using namespace std;
    
    const int MAX = 5001;
    short int dp[MAX][MAX];
    
    int main() {
        int n, i, j;
        char str[MAX];
    
        cin >> n;
        cin >> str + 1;
        memset(dp, 0, sizeof(dp));
    
        for(i = n - 1; i >= 1; i--) {
            for(j = i + 1; j <= n; j++) {
                if(str[i] == str[j])
                    dp[i][j] = dp[i + 1][j - 1];
                else
                    dp[i][j] = min(dp[i + 1][j], dp[i][j - 1]) + 1;
            }
        }
        cout << dp[1][n] << endl;
    }
    

    仔细观察状态转移方程及状态转移图(假设横轴为i,纵轴为j,有效状态由1 <= i < j <= n刻画出来)可以发现当前状态只与横坐标为i或i + 1的状态有关,与其它状态无关,只可将dp[O(n)][O(n)]降低到dp[O(1)][O(n)],明确来说只需要dp[2][O(n)]。令初始k = 0,保存当前状态使用dp[k][O(n)],保存前一状态使用dp[1 - k][O(n)],交替使用k和1 - k达到滚动的效果,即滚动数组,代码如下,注意最终返回的是dp[1 - k][n],这是因为循环结束时,k对应i = 0时,那么1 - k即对应i = 1时。类似的,背包模型中很多都可以使用滚动数组优化。

    #include <cstring>
    #include <algorithm>
    #include <iostream>
    using namespace std;
    
    const int MAX = 5001;
    short int dp[2][MAX];
    
    int main() {
        int n, i, j;
        char str[MAX];
    
        cin >> n;
        cin >> str + 1;
        memset(dp, 0, sizeof(dp));
    
        int k = 0; //i = k, i + 1 = 1 - k
        for(i = n - 1; i >= 1; i--) {
            for(j = i + 1; j <= n; j++) {
                if(str[i] == str[j])
                    //dp[i][j] = dp[i + 1][j - 1];
                    dp[k][j] = dp[1 - k][j - 1];
                else
                    //dp[i][j] = min(dp[i + 1][j], dp[i][j - 1]) + 1;
                    dp[k][j] = min(dp[1 - k][j], dp[k][j - 1]) + 1;
            }
            k = 1 - k;
        }
        //cout << dp[1][n] << endl;
        cout << dp[1 - k][n] << endl;
    }
  • 相关阅读:
    modprobe命令
    CentOS实验七:配置RPMForge软件源
    Makefile中的cd用法
    shell 脚本重定向【转】
    自动登陆CentOS
    用UltraISO制作启动光盘
    解决PATH中没有/sbin目录的问题
    Linux系统信息命令大全
    隐藏CentOS桌面图标
    IIS 操作必须使用一个可更新的查询的解决方法
  • 原文地址:https://www.cnblogs.com/shuaihanhungry/p/5772059.html
Copyright © 2011-2022 走看看