Openjudge2.6基本算法之动态规划8471:切割回文
题目传送门
最近做了几道同类型的题,像这种按条件分割区间的题一般都需要先预处理出任意i到j区间是否符合条件
所以:
for(int k=1;k<=len;k++)
{
for(int i=1;i+k-1<=len;i++)
{
int j=k+i-1;
if(k<=2)
{
if(s[i]==s[j]) b[i][j]=1;
}
else
{
if(b[i+1][j-1]&&s[i]==s[j]) b[i][j]=1;
}
}
}
这段代码是预处理出任意i到j是否是回文串,挺考验代码能力的。
处理出回文串判断之后就是状态转移方程了,方程挺简单的,设f[i]表时从1到i满足条件时的最小段数,状态转移方程:if(b[j][i]) f[i]=min(f[i],f[j-1]+1) 如果当前串是回文串就决策短还是不断。
另:各种初始化别忘了!!!
AC代码:
#include<bits/stdc++.h>
using namespace std;
int t,f[1005],len,b[1005][1005];
char s[1005];
int main()
{
scanf("%d",&t);
while(t--)
{
memset(f,0x3f,sizeof(f));
memset(b,0,sizeof(b));
scanf("%s",s+1);
len=strlen(s+1);
for(int k=1;k<=len;k++)
{
for(int i=1;i+k-1<=len;i++)
{
int j=k+i-1;
if(k<=2)
{
if(s[i]==s[j]) b[i][j]=1;
}
else
{
if(b[i+1][j-1]&&s[i]==s[j]) b[i][j]=1;
}
}
}
f[0]=0;
for(int i=1;i<=len;i++)
{
for(int j=0;j<=i;j++)
{
if(b[j][i]) f[i]=min(f[i],f[j-1]+1);
}
}
printf("%d\n",f[len]-1);
}
return 0;
}