题目链接:https://cn.vjudge.net/contest/318859#problem/B
题意:一个人要去参加派对,不同的派对要穿不同的衣服。现在给出每个派对的要穿的衣服,已知这个人可以多穿衣服或者脱去一定的衣服,但每一件衣服脱去了之后就不能再穿了。求这个人需要穿的最少的衣服。
思路:又是一道让我自闭的区间DP“入门题”,状态方程不是很好想,需要仔细去理解,现在对我来说难点就是怎样找到最小子结构,还是需要多多练习刷题才行。
设dp[i][j]为一个区间i到j需要的最少衣服数,则这个人到第j个派对的时候,有两种决策:
①不用管前面的情况,当前可以直接穿上第j个派对需要的衣服,则此时的状态转移方程为dp[i][j]=min(dp[i][j], dp[i][j-1]+1)
②与第一种决策相反,脱去一定的衣服,如果有在[i,j-1]之间有c[k]=c[j],则可以认为把衣服脱到k派对时的衣服,再去参加j派对,则转移方程为
dp[i][j]=min(dp[i][j], dp[i][k] + dp[k+1][j-1]
#include<iostream>
#include<cstring>
using namespace std;
const int INF = 0x3f3f3f3f;
int c[105];
int dp[105][105];
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
int t;
cin >> t;
for(int kase = 1; kase <= t; ++kase)
{
int n;
cin >> n;
for(int i = 1; i <= n; ++i)
cin >> c[i];
for(int i = 1; i <= n; ++i)
for(int j = i; j <= n; ++j)
dp[i][j] = j-i+1;
cout << "Case " << kase << ": ";
for(int len = 1; len <= n; ++len){
for(int i = 1; i+len <= n; ++i){
dp[i][i+len] = dp[i][i+len-1] + 1;
for(int k = i; k <= i+len-1; ++k){
if(c[i+len] == c[k])
dp[i][i+len] = min(dp[i][i+len], dp[i][i+len-1]);
}
}
}
cout << dp[1][n] << endl;
}
return 0;
}