NBUT 1586 买票回家啦 区间dp
给定一个字符串,问最少删除多少个字符串可以将字符串变成一个回文串。
使用区间dp。 dp[i][j] 表示字符串 s[i],⋯,s[j] 删除最少多少个字符可以变成回文串。当 s[i]==s[j] 时, dp[i][j]=dp[i+1][j−1] (注意字符串长度为2时要特判);否则, dp[i][j]=min(dp[i+1][j]+1,dp[i][j−1]+1) 。即两边相等的时候,都不用删除,两边不等的时候,取删除最少字符的那个。
代码:
/*************************************************************************
> File Name: j.cpp
> Author: gwq
> Mail: gwq5210@qq.com
> Created Time: 2015年05月01日 星期五 14时20分17秒
************************************************************************/
#include <cmath>
#include <ctime>
#include <cctype>
#include <climits>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <string>
#include <vector>
#include <sstream>
#include <iostream>
#include <algorithm>
#define INF (INT_MAX / 10)
#define clr(arr, val) memset(arr, val, sizeof(arr))
#define pb push_back
#define sz(a) ((int)(a).size())
using namespace std;
typedef set<int> si;
typedef vector<int> vi;
typedef map<int, int> mii;
typedef long long ll;
const double esp = 1e-5;
#define N 1010
int dp[N][N];
char s[N];
int main(int argc, char *argv[])
{
int t;
scanf("%d", &t);
while (t--) {
scanf("%s", s);
clr(dp, 0);
int len = strlen(s);
for (int k = 1; k < len; ++k) {
for (int i = 0; i + k < len; ++i) {
int j = i + k;
if (s[i] == s[j]) {
// 处理长度为2的特殊情况
if (j > i + 1) {
dp[i][j] = dp[i + 1][j - 1];
}
} else {
dp[i][j] = min(dp[i][j - 1] + 1, dp[i + 1][j] + 1);
}
}
}
printf("%d\n", dp[0][len - 1]);
}
return 0;
}