這個題是DP的經典題目,主要思想及狀態轉移在於:一個位置需要切割的刀數,等於從之前到他最長的迴文序列,之前的那個元素切割的刀數+1,或者如果他與之前的無法構成迴文序列,則等於之前那個位置所需要切割的刀數+1
DP太不熟練了......真的需要多練了...
#include <iostream>
#include <cstring>
using namespace std;
int judgethereverse(char s[],int start,int end)//這裏需要採用線性judge 找尋第[start,end]
//採用 計算機下標
{
//假設abcdefg 找尋 都2到5 2到6位
// 0123456
int length = end-start+1;
if(length%2==0)//如果是偶數位
{
int temp = (start+end+1)/2;
int count = 0;
for(int i=start;i<temp;i++)//
{
// printf("%c\t%c\n",s[i],s[end-count]);
if(s[i]!=s[end-count])
{
return 0;
}
count ++;
}
return 1;
}
else if(length%2!=0)//如果是奇數位abcdcba
// 0123456
{
int temp = (start+end)/2;
int count = 0;
for(int i=start;i<temp;i++)
{
// printf("%c\t%c\n",s[i],s[end-count]);
if(s[i]!=s[end-count])
{
return 0;
}
count ++;
}
return 1;
}
}
int main(void)
{
int t;
scanf("%d\n",&t);
while(t--)
{
char s[1005];
scanf("%s",s);
int lens = strlen(s);
int dp[1005];//表示這個位置需要的切割數
for(int i=1;i<=lens;i++)
{
dp[i] = i-1;//這個位置默認需要的切割數
}
for(int i=0;i<lens;i++)
{
if(judgethereverse(s,0,i)==1)
{
dp[i+1] = 0;
}
else
{
dp[i+1] = dp[i] + 1;
for(int j=1;j<i;j++)
{
if(judgethereverse(s,j,i)==1)
{
dp[i+1] = dp[j] + 1; //這裏爲什麼是dp j 因爲這裏角標差了1 所以不是j-1
break;
}
}
}
}
// for(int i=1;i<=lens;i++)
// {
// printf("%d",dp[i]);
// }
printf("%d\n",dp[lens]);
/*如果能從0位開始構成迴文 則那個位置的切割數是0
如果不能 則從第1位開始找,有沒有能和這個位置構成迴文的
如果有則找到這些迴文中“長度最長的”默認這一段切割掉 此時這個位置的所需切割數
等於這個位置之前的切割數+1
如果在這些裏也沒有找到迴文的 則這個位置的長度等於其前一位的切割長度+1
總結:一個位置的切割長度
迴文要麼存在於從第一位開始到某一位
要麼存在於 順序遍歷 往回的查找即 2-1 3-1 -32 4-1 4-2 4-3 4-4中
一個位置的切割回文數情況 等於其前邊的迴文數情況+1 與 它所構成迴文序列之前的 數字+1 之間的最小值
*/
}
}//dynamic Programming