HDU 2476 String painter(区间DP)

Posted jpphy0

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 2476 String painter(区间DP)相关的知识,希望对你有一定的参考价值。

String painter

http://acm.hdu.edu.cn/showproblem.php?pid=2476

分析

  • 任意两次操作,要么不重叠,要么前一次包含后一次;若部分重叠,则前一次操作可以放弃对重叠部分的操作
  • 区间(i,j)被操作后,应出现A[i] == B[i] 且 A[j] == B[j],即首、尾对应字符应一致;理由:
    • 若A[j] != B[j],则应操作区间(i,j-1)
    • 同理,若A[i] != B[i],则应操作区间(i-1,j)
    • 操作前不比操作后差(操作前可能对应一致,但操作后对应不一致),应不操作
  • 若区间(i,j)不满足B[i] == B[j],则不应将(i,j)作为一个被操作的区间
  • 若区间(i,j)内,存在 B [ k 1 ] = = B [ k 2 ] = = B [ k 3 ] = = … = = B [ k m ] B[k_1] == B[k_2] == B[k_3] == … == B[k_m] B[k1]==B[k2]==B[k3]====B[km],则包含 k 1 k_1 k1的操作区间只能是:
    • ( k 1 , k 1 ) (k_1,k_1) (k1k1)
    • ( k 1 , k 2 ) (k_1,k_2) (k1k2)
    • ( k 1 , k 3 ) (k_1,k_3) (k1k3)
    • ……
    • ( k 1 , k m ) (k_1,k_m) (k1km)

思路1

  • dp(i, j, k)的定义:源串A在区间(i,j)内的所有字符都是k时的最优解
  • f(i, j)的定义:区间(i,j)的最优解

思路2

  • dp(i, j)的定义:源串A在区间(i,j)与目标串B无对应字符相同时的最优解
  • 设B串的区间(3,14)为: a 3 b 4 c 5 d 6 a 7 e 8 f 9 a 10 h 11 a 12 i 13 j 14 a^3b^4c^5d^6a^7e^8f^9a^{10}h^{11}a^{12}i^{13}j^{14} a3b4c5d6a7e8f9a10h11a12i13j14,【3,7,10,12都是a】
    • 在区间(4,14)中,位置7上的a,有三种可能区间操作,即(7,7)、(7,10)和(7,12)
    • 若将区间扩展到(3,14),相应的把区间操作扩展到(3,7)、(3,10)和(3,12),都不会改变操作次数
    • 状态转移方程
      • dp[3][14] = min(dp[3][14],dp[3][3]+dp[4][14]),(3,3)单独操作,(4,14)一起操作
      • dp[3][14] = min(dp[3][14],dp[4][7]+dp[8][14]),(3,7)一起操作,(8,14)一起操作
      • dp[3][14] = min(dp[3][14],dp[4][10]+dp[11][14]),(3,10)一起操作,(11,14)一起操作
      • dp[3][14] = min(dp[3][14],dp[4][12]+dp[13][14]),(3,12)一起操作,(13,14)一起操作
  • f(i)的定义:区间(1,i)的最优解
    • 按最后一个不变的字符分类

代码

思路1【202MS】

#include<bits/stdc++.h>
using namespace std;
#define MXN 110
#define INF 0x3f3f3f3f
int N, nxt[MXN], C[256], dp[MXN][MXN][26], f[MXN][MXN];
string A, B;
int main(){
	int s, t, tmp;
	while(cin >> A >> B){
		N = A.size();
		for(int i = 0; i < 256; i++) C[i] = N;
		for(int i = N-1; i >= 0; i--){
			nxt[i] = C[B[i]];
			C[B[i]] = i;
		}
		memset(dp, INF, sizeof dp);
		memset(f, INF, sizeof f);	
		for(int i = 1; i <= N; i++){ // 长度	
			for(int j = 0; j <= N - i; j++){ // 起点
				for(char k = 'a'; k <= 'z'; k++){
					s = j, t = j+i-1;
					while(s <= t){
						tmp = B[j] == k ? 0 : 1;
						if(j+1 <= s-1) tmp += dp[j+1][s-1][B[j]-'a'];
						if(s+1 <= t) tmp += dp[s+1][t][k-'a'];
						dp[j][t][k-'a'] = min(dp[j][t][k-'a'], tmp);
						s = nxt[s];
					}
				}
			}
		}
		for(int i = 1; i <= N; i++){
			for(int j = 0; j <= N-i; j++){
				s = j, t = j+i-1;
				while(s <= t){
					if(B[j] == A[j] && B[s] == A[s])
						tmp = (j+1 <= s-1) ? f[j+1][s-1] : 0;
					else{
						tmp = (j+1 <= s-1) ? dp[j+1][s-1][B[j]-'a'] : 0;
						tmp += 1;
					}
					if(s+1 <= t) tmp += f[s+1][t];
					f[j][t] = min(f[j][t], tmp);
					s = nxt[s];
				}
			}
		}
		printf("%d\\n", f[0][N-1]);
	} 
	return 0;
}

思路2【0-15MS】

// hdu 2476 String painter
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define MXN 110
char A[MXN], B[MXN];
int dp[MXN][MXN], n, f[MXN], nxt[MXN];
int main() {
	int s, t, tmp;
	while (scanf("%s%s", A+1, B+1) == 2) {
		n = 0;
		while(A[n+1]) n++;
		for(int i = 1; i <= 256; ++i) f[i] = n+1;
		for(int i = n; i >= 1; --i) nxt[i] = f[B[i]], f[B[i]] = i;
		for(int i = 1; i <= n; ++i) dp[i][i] = 1;
		for(int len = 2; len <= n; ++len){
			for(int j = 1; j <= n; ++j){
				s = j, t = j+len-1;
				if(t > n) break;
				dp[j][t] = dp[j+1][t]+1;
				s = nxt[s];				
				while(s <= t){
					tmp = dp[j+1][s];
					if(s+1 <= t) tmp += dp[s+1][t];
					dp[j][t] = min(dp[j][t], tmp);
					s = nxt[s];
				}
			}
		}
		f[0] = 0;
		for(int i = 1; i <= n; ++i){
			f[i] = f[i-1] + (A[i] == B[i] ? 0 : 1);
			for(int j = 0; j < i; ++j){
				f[i] = min(f[i], f[j]+dp[j+1][i]);
 			}
		}
		printf("%d\\n", f[n]);
	}
	return 0;
}

稍繁

// hdu 2476 String painter
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define MXN 150
char A[MXN], B[MXN];
int dp[MXN][MXN], n, f[MXN], nxt[MXN];
int main() {
	int s, t, tmp;
	while (scanf("%s%s", A+1, B+1) == 2) {
		n = 0;
		while(A[n+1]) n++;
		for(int i = 1; i <= 256; ++i) f[i] = n+1;
		for(int i = n; i > 0; --i) {
            nxt[i] = f[B[i]];
			f[B[i]] = i;
		}
		for(int i = 1; i <= n; ++i) dp[i][i] = 1;
		for(int len = 2; len <= n; ++len){
			for(int j = 1; j <= n; ++j){
				s = j, t = j+len-1;
				if(t > n) break;
				dp[j][t] = dp[j+1][t]+1;
				s = nxt[s];				
				while(s <= t){
					tmp = dp[j+1][s];
					if(s+1 <= t) tmp += dp[s+1][t];
					dp[j][t] = min(dp[j][t], tmp);
					s = nxt[s];
				}
			}
		}
        for(int i = n; i >= 0; --i) nxt[i] = A[i+1] hdu2476String painter (区间DP)

hdu 2476 String Painter

HDU 2476 String painter(区间dp)

HDU 2476 String painter

hdu 2476 String painter(区间dp)

String painter (hdu 2476 DP好题)