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) (k1,k1)
- ( k 1 , k 2 ) (k_1,k_2) (k1,k2)
- ( k 1 , k 3 ) (k_1,k_3) (k1,k3)
- ……
- ( k 1 , k m ) (k_1,k_m) (k1,km)
思路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)