【题解】LuoGu2470:[SCOI2007]压缩

原题传送门
这道题跟这道很像,差别在于本题无法嵌套
d p i , j , 0 / 1 dp_{i,j,0/1} dpi,j,0/1表示区间 [ l , r ] [l,r] [l,r]中有/无 M M M的答案,默认在 i − 1 i-1 i1的地方有一个 M M M
转移:

  • 若区间前半段和后半段相等, d p i , j , 0 = d p i , m i d , 0 + 1 dp_{i,j,0}=dp_{i,mid,0}+1 dpi,j,0=dpi,mid,0+1
  • d p i , j , 0 = m i n ( d p i , k + j − k ) dp_{i,j,0}=min(dp_{i,k}+j-k) dpi,j,0=min(dpi,k+jk)
  • d p i , j , 1 = m i n ( m i n ( d p i , k , 0 , d p i , k , 1 ) + 1 + m i n ( d p k + 1 , j , 0 , d p k + 1 , j , 1 ) ) dp_{i,j,1}=min(min(dp_{i,k,0},dp_{i,k,1})+1+min(dp_{k+1,j,0},dp_{k+1,j,1})) dpi,j,1=min(min(dpi,k,0,dpi,k,1)+1+min(dpk+1,j,0,dpk+1,j,1))(枚举 M M M的位置)

a n s = m i n ( d p 1 , n , 0 , d p 1 , n , 1 ) ans=min(dp_{1,n,0},dp_{1,n,1}) ans=min(dp1,n,0,dp1,n,1)

Code:

#include 
#define maxn 110
using namespace std;
char s[maxn];
int dp[maxn][maxn][2], n;

bool check(int l, int r){
	if ((r - l + 1) % 2 != 0) return 0;
	int mid = (l + r) >> 1;
	for (int i = l; i <= mid; ++i) if (s[i] != s[mid + i - l + 1]) return 0;
	return 1;
}

int main(){
	scanf("%s", s + 1); n = strlen(s + 1);
	memset(dp, 0x3f, sizeof(dp));
	for (int i = 1; i <= n; ++i)
		for (int j = i; j <= n; ++j) dp[i][j][0] = dp[i][j][1] = j - i + 1;
	for (int l = 2; l <= n; ++l)
		for (int i = 1, j = i + l - 1; j <= n; ++i, ++j){
			if (check(i, j)) dp[i][j][0] = dp[i][(i + j) >> 1][0] + 1;
			for (int k = i; k < j; ++k) dp[i][j][0] = min(dp[i][j][0], dp[i][k][0] + j - k);
			for (int k = i; k < j; ++k) dp[i][j][1] = min(dp[i][j][1], min(dp[i][k][0], dp[i][k][1]) + min(dp[k + 1][j][0], dp[k + 1][j][1]) + 1);
		}
	printf("%d\n", min(dp[1][n][0], dp[1][n][1]));
	return 0;
}

你可能感兴趣的:(题解,LuoGu,DP)