原题地址
。差不多是个水题罢,难度个人认为是红
设
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j]表示区间
[
i
,
j
]
[i,j]
[i,j]与答案匹配,考虑区间dp
若
i
=
j
i=j
i=j,则
d
p
[
i
]
[
j
]
=
1
dp[i][j]=1
dp[i][j]=1,显然
若
s
[
i
]
=
s
[
j
]
s[i]=s[j]
s[i]=s[j],则
d
p
[
i
]
[
j
]
=
m
i
n
(
d
p
[
i
+
1
]
[
j
]
,
d
p
[
i
]
[
j
−
1
]
)
dp[i][j]=min(dp[i+1][j],dp[i][j-1])
dp[i][j]=min(dp[i+1][j],dp[i][j−1]),相当于给
[
i
,
j
−
1
]
或
[
i
+
1
,
j
]
[i,j-1]或[i+1,j]
[i,j−1]或[i+1,j]刷一下,然后带着
i
i
i或
j
j
j一起刷qwq
若
s
[
i
]
≠
s
[
j
]
s[i]\not=s[j]
s[i]=s[j],则
d
p
[
i
]
[
j
]
=
M
i
n
k
=
i
k
<
j
d
p
[
i
]
[
k
]
+
d
p
[
k
+
1
]
[
j
]
dp[i][j]=Min_{k=i}^{k<j}dp[i][k]+dp[k+1][j]
dp[i][j]=Mink=ik<jdp[i][k]+dp[k+1][j],分两个更小的区间涂,枚举断点。
假的蓝题。
C
o
d
e
\color{blue}Code
Code:
# include <bits/stdc++.h>
using namespace std;
string s;
int n;
int dp[700][700];
void solve(void)
{
for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) dp[i][j]=INT_MAX;
for(int len=1;len<=n;len++)
{
for(int i=1;i<=n;i++)
{
int j=i+len-1;
if(len==1)
{
dp[i][j]=1;
}
else
{
if(s[i-1]==s[j-1])
{
dp[i][j]=min(dp[i+1][j],dp[i][j-1]) ;
}
else
{
for(int k=i;k<j;k++)
{
dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]) ;
}
}
}
}
}
cout<<dp[1][n]<<endl;
return ;
}
int main(void)
{
cin >> s;
n=s.size() ;
solve() ;
return 0;
}