!-- Loading 底层遮罩 -->

CF607B Zuma

感谢所有AC

传送门

思路

      比较典型的区间转移。状态定义为 f( i , j ) 为从消除 i 到 j 区间的宝石的最小时间。

     考虑从区间两端和区间内部进行转移。

     如果一个区间的两端相等,形如 aSa,如果 S 是一个回文串,那么它的最小时间为 1 ,而 aSa 时间代价也是 1 ,如果 S 不是一个回文串,那么对 S 进行消除直到 S 串只剩下最后一个回文串(可以是一个或多个字符),剩下的最后一个回文串和两端的 a 也组成回文串,时间代价为 1 。可以发现不管 S 是什么类型,只要出现区间的两端相等的情况下,f( i , j )的时间代价和 f( i+1, j-1 )就是一样的。

     对于一个两端不相等的区间,枚举断点,划分区间,进行比较并取最小值(因为可能一个区间由两个回文串来组成,那么这个区间的时间代价为2才是正确的)。

代码

#include<iostream>
#include<cstring>
#define maxn 507
using namespace std;
int n, f[maxn][maxn], a[maxn];
int main(void)
{
	ios::sync_with_stdio(false);
	cin >> n;
	for (int i = 1; i <= n; i++)
		cin >> a[i];
	memset(f, 0x3f, sizeof(f));
	for(int L=0;L<n;L++)
		for (int i = 1, j = i + L; j <= n; i++, j++) {
			if (a[i] == a[j])
				f[i][j] = L < 2 ? 1 : f[i + 1][j - 1];
			for (int k = i; k < j; k++)
				f[i][j] = min(f[i][j], f[i][k] + f[k + 1][j]);
		}
	cout << f[1][n] << '\n';
	return 0;
}

 

posted @ 2022-04-07 19:17  Thinker-X  阅读(40)  评论(0)    收藏  举报