原题:
F. Clear the String
time limit per test3 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
You are given a string s of length n consisting of lowercase Latin letters. You may apply some operations to this string: in one operation you can delete some contiguous substring of this string, if all letters in the substring you delete are equal. For example, after deleting substring bbbb from string abbbbaccdd we get the string aaccdd.
Calculate the minimum number of operations to delete the whole string s.
Input
The first line contains one integer n (1≤n≤500) — the length of string s.
The second line contains the string s (|s|=n) consisting of lowercase Latin letters.
Output
Output a single integer — the minimal number of operation to delete string s.
Examples
input
5
abaca
output
3
input
8
abcddcba
output
4
中文:
给你一个字符串,每次可以去掉字符串中的一个连续的子串,这个连续的子串必须所有的字符都相同,问你最少去掉多少次可以将整个字符串去掉。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=501;
int dp[maxn][maxn];
int n;
char s[maxn];
int main()
{
ios::sync_with_stdio(false);
while(cin>>n)
{
cin>>&s[1];
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;i++)
dp[i][i]=1;
for(int len=1;len<n;len++)
{
for(int i=1;i<=n-len;i++)
{
int j=i+len;
dp[i][j]=dp[i+1][j]+1;
for(int k=i+1;k<=j;k++)
{
if(s[i]==s[k])
dp[i][j]=min(dp[i][j],dp[i+1][k-1]+dp[k][j]);
}
}
}
cout<<dp[1][n]<<endl;
}
return 0;
}
思路:
区间dp
设置状态为dp[i][j]表示i到j的子串全部去掉需要的最少步数,设字符串为s
状态转移方程为
d p [ i ] [ j ] = m i n ( d p [ i + 1 ] [ j ] + 1 , d p [ i + 1 ] [ k − 1 ] + d p [ k ] [ j ] ) dp[i][j]=min(dp[i+1][j]+1,dp[i+1][k-1]+dp[k][j]) dp[i][j]=min(dp[i+1][j]+1,dp[i+1][k−1]+dp[k][j])
d
p
[
i
+
1
]
[
j
]
+
1
dp[i+1][j]+1
dp[i+1][j]+1表示去掉第i个字符,
d
p
[
i
+
1
]
[
k
−
1
]
+
d
p
[
k
]
[
j
]
dp[i+1][k-1]+dp[k][j]
dp[i+1][k−1]+dp[k][j]表示当第k个字符与第i个字符相同时,可以先把中间[i+1,k-1]个字符串先处理了,使得第i个字符与第k个字符相邻,因为第i个字符与第k个字符相同,那么在执行dp[k][j]时可以在消除第k个字符时顺带将第i个字符一并消除。