题目大意:按照祖玛的玩法(随意选颜色),给出一段区间,问最少用多少个球能够把所有颜色块都消除。
思路:把输入数据按照连续的块处理,保存成颜色和数量,然后用这个来DP。我们知道,一个单独的块需要两个相同的颜色可以消去,对于这样的块f[i][i] = 2,其余的>=2个的块只需要一个,这样的块f[i][i] = 1。转移就比较简单了,按照区间DP的一般思想,最外层循环的是区间长度,中间循环的是起始位置,最后循环的是松弛变量。特殊情况是这个区间的两边是同一种颜色,多加一个转移方程。
CODE:
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define MAX 510 using namespace std; pair<int,int> arr[MAX]; int cnt,src[MAX],total; int f[MAX][MAX]; int main() { cin >> cnt; for(int i = 1; i <= cnt; ++i) scanf("%d",&src[i]); int last = src[1],num = 0; for(int i = 1; i <= cnt; ++i) { if(src[i] != last) { arr[++total] = make_pair(last,num); last = src[i]; num = 1; } else ++num; } arr[++total] = make_pair(last,num); memset(f,0x3f,sizeof(f)); for(int i = 1; i <= total; ++i) if(arr[i].second == 1) f[i][i] = 2; else f[i][i] = 1; for(int k = 2; k <= total; ++k) for(int i = 1; i + k - 1 <= total; ++i) { if(arr[i].first == arr[i + k - 1].first) f[i][i + k - 1] = f[i + 1][i + k - 2] + (arr[i].second + arr[i + k - 1].second == 2 ? 1:0); for(int j = 1; j < k; ++j) f[i][i + k - 1] = min(f[i][i + k - 1],f[i][i + j - 1] + f[i + j][i + k - 1]); } cout << f[1][total] << endl; return 0; }
时间: 2024-10-15 11:12:43