题目链接:
http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=27130
-------------------------------------------------------------------------------------------------
模拟一下整个过程是一个栈的操作 很难想到会是区间$DP$
不过多想想或许可以发现 对于一个栈内元素 显然会有一堆连续的元素在它之后入栈和出栈
$($栈的特殊性就是 在它之后入栈的一定比它先出栈 所以是连续的一段$)$
而我们此时则可以根据这个栈底元素入栈后再一次成为栈顶元素的时候来对区间进行划分
$($实际上也就是题意中 穿上某件服装后 再一次地使得它成为最外面的一件$)$
于是转移方程可以写为
$f[i][j] = f[i + 1][j] + 1 ($第$i$个聚会所用服装未被多次利用$)$
$f[i][j] = min(f[i][k - 1] + f[k + 1][j]) ($第$i$个聚会所用服装在第$k$个聚会被再次利用$)$
1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <algorithm> 5 using namespace std; 6 int c[110], f[110][110]; 7 int t, n; 8 int main() 9 { 10 scanf("%d", &t); 11 for(int ca = 1; ca <= t; ++ca) 12 { 13 scanf("%d", &n); 14 for(int i = 1; i <= n; ++i) 15 scanf("%d", &c[i]); 16 for(int i = 1; i <= n; ++i) 17 f[i][i] = 1; 18 for(int len = 1; len <= n; ++len) 19 for(int i = 1; i + len - 1 <= n; ++i) 20 { 21 int j = i + len -1; 22 f[i][j] = f[i + 1][j] + 1; 23 for(int k = i + 1; k <= j; ++k) 24 if(c[i] == c[k]) 25 f[i][j] = min(f[i][j], f[i][k - 1] + f[k + 1][j]); 26 } 27 printf("Case %d: %d ", ca, f[1][n]); 28 } 29 return 0; 30 }