1. 程式人生 > >poj3280(區間dp,好題)

poj3280(區間dp,好題)

給你長度為m的字串,其中有n種字元,每種字元都有兩個值,分別是插入這個字元的代價,刪除這個字元的代價,讓你求將原先給出的那串字元變成一個迴文串的最小代價。

dp[i][j]代表區間i到區間j成為迴文串的最小代價,那麼對於dp[i][j]有三種情況:

1、dp[i+1][j]表示區間i到區間j已經是迴文串了的最小代價,那麼對於s[i]這個字母,我們有兩種操作,刪除與新增,對應有兩種代價,dp[i+1][j]+add[s[i]],dp[i+1][j]+del[s[i]],取這兩種代價的最小值;

2、dp[i][j-1]表示區間i到區間j-1已經是迴文串了的最小代價,那麼對於s[j]這個字母,同樣有兩種操作,dp[i][j-1]+add[s[j]],dp[i][j-1]+del[s[j]],取最小值

3、若是s[i]==s[j],dp[i+1][j-1]表示區間i+1到區間j-1已經是迴文串的最小代價,那麼對於這種情況,我們考慮dp[i][j]與dp[i+1][j-1]的大小........

然後dp[i][j]取上面這些情況的最小值.........//考慮的情況好多

本題總結:

注意資料範圍,m=2000,確定n^2的演算法,兩個迴圈

和最大括號匹配一樣,dp【i】【j】還是表示的i~j這個區間內的狀態,不過這個是二維的,

既然是二維的,且狀態和演算法時間複雜度同階,那麼,dp【i】【j】就一定是從它旁邊的狀態推出來的,而不是列舉以前的狀態,找的

這個題需要考慮的情況不少,狀態轉移方程還是要練,找感覺,這是現在的不足之處,要鍛鍊得

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<string>
using namespace std;
int n,m,dp[2009][2009],in[27],de[27];
char ch[2009];
int main()
{
	scanf("%d%d",&n,&m);
	scanf("%s",ch);
	for (int i=1;i<=n;i++) 
	{
		char c;
		if (scanf("%c",&c)&&c=='\n') scanf("%c",&c);
		int k1,k2;
		scanf("%d%d",&k1,&k2);
		in[c-'a']=k1;de[c-'a']=k2;
	}
	for (int i=m-1;i>=0;i--)
	{
		dp[i][i]=0;
		for (int j=i+1;j<m;j++)
		{
			dp[i][j]=0x3f3f3f3f;//因為找最小的,別忘了開始時置為無窮大
			if (ch[i]==ch[j]) dp[i][j]=dp[i+1][j-1];
			dp[i][j]=min(dp[i][j],min(dp[i+1][j]+in[ch[i]-'a'],dp[i+1][j]+de[ch[i]-'a']));
			dp[i][j]=min(dp[i][j],min(dp[i][j-1]+in[ch[j]-'a'],dp[i][j-1]+de[ch[j]-'a']));//三種情況
			//printf("%d %d %d\n",i,j,dp[i][j]);
		}
	}
	printf("%d",dp[0][m-1]);
	return 0;
}



相關推薦

poj3280(區間dp)

給你長度為m的字串,其中有n種字元,每種字元都有兩個值,分別是插入這個字元的代價,刪除這個字元的代價,讓你求將原先給出的那串字元變成一個迴文串的最小代價。 dp[i][j]代表區間i到區間j成為迴文串的最小代價,那麼對於dp[i][j]有三種情況: 1、dp[i+1]

bzoj2287【POJ Challenge】消失之物(dp+補集轉化)

std gree scanf online discus 技術 bsp lin geo 2287: 【POJ Challenge】消失之物 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 657 Solved: 382

CodeForces - 793D 區間dp記憶化

記憶化 ini %d 單向 ble targe set skip ref CodeForces - 793D 題意:一條筆直街道上有標號為 1~n 的 n 個點,有 m 條帶邊權的單向邊。要找一條經過 k 個點的路徑和,限制:每次走過的邊不能跨過已走過的點。 比如點 3

The Doors(幾何+最短路)

The Doors http://poj.org/problem?id=1556 Time Limit: 1000MS   Memory Limit: 10000K Total Submis

Escape(狀態壓縮+最大流)

  Escape http://acm.hdu.edu.cn/showproblem.php?pid=3605 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (

Marriage Match II(二分+並查集+最大流)

Marriage Match II http://acm.hdu.edu.cn/showproblem.php?pid=3081 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768

【LightOJ - 1031】Easy Game (區間dp博弈)

題幹: You are playing a two player game. Initially there are n integer numbers in an array and player A and B get chan

Tourism Planning 狀態壓縮DP

Tourism Planning Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1125    Accepte

E. Bus Video System(找剛開始車上滿足的人數細節多)

The busses in Berland are equipped with a video surveillance system. The system records information about changes in the number of passengers in a bus afte

Codeforces Round #312 (Div. 2) (第三是位運算

分析:從0座標分開,負半軸一個數組,正半軸一個數組,來記錄果樹的左邊和數量,可以用結構體陣列來儲存資料,其中少的一個半軸上的果樹肯定會全被採光,而多的一邊樹上會多采一棵樹。 struct p{ int num,x; } p neg[105],pos[105];這樣表

Supermarket(並查集

Supermarket Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 11154 Accepted: 4910 Description A supermarket has a set Prod of products on

石子歸併(區間dp的模板)

石子歸併 題 意:N堆石子擺成一條線。現要將石子有次序地合併成一堆。規定每次只能選相鄰的2堆石子合併成新的一堆,並將新的一堆石子數記為該次合併的代價。計算將N堆石子合併成一堆的最小代價。 例如: 1 2 3 4,有不少合併方法 1 2 3 4 => 3 3 4(3) =>

codeforces 878C Tournament平衡樹!!!!

C. Tournament time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output

bzoj1150 堆應用

#include<bits/stdc++.h> using namespace std; #define maxn 100005 #define INF 0x3fffffff #define pa pair<int,int> int n,k,pre[maxn],nxt[maxn

983B XOR-pyramid(區間dp異或)

#include<algorithm> #include<iostream> #include<cstdlib> #include<cstring> #include<cstdio> #include<cmath> #include&l

POJ2955 Brackets(區間DP括號匹配)

POJ2955 首先考慮怎麼樣定義dp讓它滿足具有通過子結構來求解、 定義dp [ i ] [ j ] 為串中第 i 個到第 j 個括號的最大匹配數目 那麼我們假如知道了 i 到 j 區間的最大匹

51nod 1009 數字1的數量 (統計1的總個數

給定一個十進位制正整數N,寫下從1開始,到N的所有正數,計算出其中出現所有1的個數。 例如:n = 12,包含了5個1。1,10,12共包含3個1,11包含2個1,總共5個1。 Input 輸入N(1 <= N <= 10^9) Outp

POJ 1191 棋盤分割 (區間DP記憶化搜索)

bool for ring def bsp sca printf namespace http 題面 思路:分析公式,我們可以發現平均值那一項和我們怎麽分的具體方案無關,影響答案的是每個矩陣的矩陣和的平方,由於數據很小,我們可以預處理出每個矩陣的和的平方,執行狀態轉移。 設

區間DP子問題的深刻理解

問題描述   有n個矩陣,大小分別為a0*a1, a1*a2, a2*a3, ..., a[n-1]*a[n],現要將它們依次相乘,只能使用結合率,求最少需要多少次運算。   兩個大小分別為p*q和q*r的矩陣相乘時的運算次數計為p*q*r。 輸入格式   輸入的第一行包含一個整數n,表示矩陣的個數

660E Different Subsets For All Tuples (組合數學&DP

考慮dp dp[i][j]表示長度為i,以字元j結尾的答案是多少 dp[i][j]=sigma(dp[i-1][k]*2-dp[pre[j]-1][k]) 然後這個玩意兒顯然對於任意的j的都是一樣的,而且pre[j]前面的每個位置都是可能的,這裡的dp是個字首和,所以直接扣除就可以了 那麼直接化簡為:dp[