BJUTACM 1031:切割回文

這個題是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 

 

發佈了85 篇原創文章 · 獲贊 21 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章