Miraclys

一言(ヒトコト)

[USACO07OPEN]Cheapest Palindrome G

\(\large{题目链接}\)
\(\\\)
\(\Large\textbf{Solution: } \large{考虑区间dp。设f_{i,j}表示\left[ i,j\right] 构成回文的最小价值。\\如果c_i = c_j那么f_{i,j} = \min (f_{i, j}, f_{i+1,j-1})。然后考虑一般情况,要么f_{i,j}从f_{i + 1,j}转移过来,增加或者删去i,反之一样。}\)
\(\\\)
\(\Large\textbf{Summary: } \large{区间dp有几种转移方式。\\1. f_{i,j}由f_{i,k}和f_{k + 1,j}转移过来。这个时候需要外层由小到大枚举区间长度,内层枚举起点,最里层枚举断点,转移即可。\\2.f_{i,j}由f_{i + 1,j}和f_{i,j - 1}转移过来,此时只需枚举区间长度与起点即可。}\)
\(\\\)
\(\Large\textbf{Code: }\)

#include <bits/stdc++.h>
using namespace std;

const int N = 2005;

int n, m, a[N], b[N], f[N][N];
char c[N], x[N];

int main() {
	scanf("%d%d%s", &n, &m, c + 1);
	int u, v;
	for (int i = 1; i <= n; ++i) scanf("%s%d%d", x, &u, &v), a[x[0] - 'a'] = u, b[x[0] - 'a'] = v;
	memset(f, 0x3f, sizeof (f));
	for (int i = 0; i <= m; ++i) f[i][i] = 0;
	for (int i = 0; i <= m; ++i) for (int j = 0; j < i; ++j) f[i][j] = 0;
	for (int k = 1; k <= m; ++k) {
		for (int i = 1; (i + k) <= m; ++i) {
			int j = i + k;
			if (c[i] == c[j]) f[i][j] = min(f[i][j], f[i + 1][j - 1]);
			f[i][j] = min(f[i][j], f[i + 1][j] + min(a[c[i] - 'a'], b[c[i] - 'a']));
			f[i][j] = min(f[i][j], f[i][j - 1] + min(a[c[j] - 'a'], b[c[j] - 'a']));
		}
	}
	cout << f[1][m] << endl;
	return 0;
} 
posted @ 2020-04-12 17:03  Miraclys  阅读(118)  评论(0编辑  收藏  举报

关于本博客样式

部分创意和图片借鉴了

BNDong

的博客,在此感谢