1. 程式人生 > >POJ1159迴文字串(DP+滾動陣列)

POJ1159迴文字串(DP+滾動陣列)

題目的大概意思就是給你一個字串,讓你在任意位置新增任意字元讓它變成一個迴文字串,求最少新增的字元數。

這是一道典型的DP,總體思路就是把逆串搞出來,兩個字串求出一個最大公共子序列的長度,然後拿n減去這個長度就可以了。

一開始想直接開二維的DP陣列,結果發現5000的長度會爆。網上學了用一個滾動陣列,因為當前狀態只與上一狀態有關,而且再先前的狀態(上上狀態)沒有儲存的意義。所以注意到0與1這兩個數字能用1-x來進行互相轉換,所以能大大節省記憶體的空間。以後感覺可能很有用。

程式碼如下:

//#include <bits/stdc++.h>
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
char str1[5005],str2[5005];
int maxlen[2][5005];
int main()
{
    int n;
    //freopen("de.txt","r",stdin);
    while (~scanf("%d",&n))
    {
        for (int i=1;i<=n;++i)
        {
            cin>>str1[i];
            str2[n+1-i]=str1[i];
        }
        str1[n+1]='\0';
        str2[n+1]='\0';
        memset(maxlen,0,sizeof maxlen);
        int e=0;//利用1-x,當x=0時1-x=1;x=1時1-x=0;
        for (int i=1;i<=n;++i)
        {
            e=1-e;//當前狀態是e,有上一個狀態1-e得出;
            for (int j=0;j<=n;++j)
            {
                if (str1[i]==str2[j])
                maxlen[e][j]=maxlen[1-e][j-1]+1;//相當於maxlen[i][j]=maxlen[i-1][j-1]+1
                else
                maxlen[e][j]=max(maxlen[e][j-1],maxlen[1-e][j]);//相當於maxlen[i][j]=max(maxlen[i][j-1],maxlen[i-1][j])
            }
        }
        cout<<n-maxlen[e][n]<<endl;//處理完成後當前狀態是e,所以輸出的是maxlen[e][n]
    }
    return 0;
}

 我看見還有200多MS過的,可能是演算法不一樣吧。另外吐槽一句,POJ不認#include <bits/stdc++.h>,交了2發CE....