UVA - 1625 Color Length (before the cost calculation sequence DP)

The meaning of problems:
Enter two lengths of the color sequence of n and m is required in order to merge the same sequence, i.e., each color can be the beginning of a new sequence into the tail sequence. For each color c, its span L (c) is equal to the difference between the maximum and minimum positions of the position. Such that the combined sequence into all the colors L (c) the sum as small as possible.

Analysis: with D [i] [j]: i-th character A indicates the front and the minimum cost sequence j B sequence of characters. How to count the cost? But to know that he's span, we should know the whole story of his position, it is difficult to obtain directly from the state in. Then need to convert the computational cost manner: After a color is not finished until all the mobile operator again, but every accumulation. When a certain color before moving to the final sequence, we need to put all the colors, "but has not ended a" of L (c) plus one. Here, "not over yet" refers to the final location has not yet reached this color in the final sequence, it may have appeared more than once, but as long as it is not the end (and there are), it will give those who have not ended plus the cost of a color, because it is in the middle of the cross.

num [i] [j]: i-th character is removed before the sequence 1, sequence 2 removed first j characters, but the number of characters already present in the final end of the sequence.
d [i] [j]: in both sequences were removed prior to the i, j characters minimum cost.
b1 [], e1 []: 1, respectively, represent a sequence start position and end position of each character. b2, e2 same.
After adding a new character to the final sequence (this sequence of characters from the head 1 or 2), but not the end of all the characters have appeared span L (c) shall be added a.
State transition equation: dp [i] [j] = min (dp [i-1] [j] + num [i-1] [j], dp [i] [j-1] + [i] num [j -1] ).

Reference: https://blog.csdn.net/CY05627/article/details/88369386 .

Code:

#include<bits/stdc++.h>
using namespace std;
const int INF = 1<<30;
const int N = 5005;
char s1[N], s2[N];
int b1[100], b2[100], e1[100], e2[100];
int d[N][N], num[N][N];
/*
num[i][j]  :取走序列1的前 i 个字符,取走序列2中前 j 个字符,在最终序列中已经出现但未结束的字符个数。
d[i][j]:在两个序列中分别取走了前 i , j 个字符的最小代价。
b1[],e1[]:分别表示序列1中每个字符的开始位置和结束位置。b2,e2一样。
向最终序列新增加一个字符后(这个字符来自序列1或2的头部),所有已经出现但未结束的字符的跨度L(c)都要加一。
状态转移方程:dp[i][j] = min( dp[i-1][j] + num[i-1][j],dp[i][j-1] + num[i][j-1] )。
*/
int main(){
	int T; scanf("%d",&T);
	while(T--){
		scanf("%s\n%s",s1+1, s2+1);
		int len1 = strlen(s1+1), len2 = strlen(s2+1),c;
		for(c = 'A'; c <= 'Z'; ++c) { b1[c] = b2[c] = INF; e1[c] = e2[c] = 0; }
		for(int i = 1; i <= len1; ++i){
			c = s1[i];
			b1[c] = min(i, b1[c]);
			e1[c] = i;
		}
		for(int i = 1; i <= len2; ++i){
			c = s2[i];
			b2[c] = min(i, b2[c]);
			e2[c] = i;
		}
		num[0][0] = 0;
		for(int i = 0; i <= len1; ++i){
			for(int j = 0; j <= len2; ++j){
				if(i){
					num[i][j] = num[i-1][j];
					c = s1[i];
					if(b1[c] == i&& b2[c] > j) ++num[i][j];
					if(e1[c] == i&& e2[c] <= j) --num[i][j];
				}
				if(j){
					num[i][j] = num[i][j-1];
					c = s2[j];
					if(b2[c] == j&& b1[c] > i) ++num[i][j];
					if(e2[c] == j&& e1[c] <= i) --num[i][j];
				}
			}
		}
		for(int i = 0; i <= len1; ++i){
			for(int j = 0; j <= len2; ++j){
				if(i==0&&j==0) continue;
				d[i][j] = INF;
				if(i) d[i][j] = min(d[i][j], d[i-1][j] + num[i-1][j]);
				if(j) d[i][j] = min(d[i][j], d[i][j-1] + num[i][j-1]);
			}
		}
		printf("%d\n",d[len1][len2]);
	}
	return 0;
}

 

Guess you like

Origin blog.csdn.net/tianwei0822/article/details/94440349