题意:告诉有n场晚会中需要穿的衣服,衣服是可以套在其他衣服外面的,
也就是说如果顺序为 1 2 1,那么可以将2套在1外面,第三场晚会需要穿1的时候把2脱掉即可,这样就只需要穿两次衣服。
题目是再告诉了顺序之后需要求出在某种序列下最少需要穿多少次衣服。
思路:区间DP,对于区间【i,j】,如果a[i]在[i+1,j]中未出现,dp[i][j] = dp[i+1][j]+1,否则a[i]应考虑是否被重复利用,若重复利用那么并不需要再一次穿上a[i],所以dp[i][j] = min(dp[i][j],dp[i][k-1],dp[k+1][j])。
#include <string.h> #include <stdio.h> #include <stdlib.h> #include <math.h> #include <iostream> #include <queue> #include <algorithm> #define MAXSIZE 1005 #define LL long long #define INF 0x3f3f3f #define mod 10056 using namespace std; int dp[MAXSIZE][MAXSIZE],a[MAXSIZE]; int Solve(int n) { for(int i=0;i<MAXSIZE;i++) { for(int j=i;j<MAXSIZE;j++) { dp[i][j] = j-i+1; } } for(int i=n;i>=1;i--) { for(int j=i+1;j<=n;j++) { dp[i][j] = dp[i+1][j] + 1; for(int k=i+1;k<=j;k++) { if(a[k] == a[i]) { dp[i][j] = min(dp[i][k-1]+dp[k+1][j],dp[i][j]); } } } } return dp[1][n]; } int main() { int T,n,cns=1; scanf("%d",&T); while(T--) { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); int ans = Solve(n); printf("Case %d: %d ",cns++,ans); } return 0; }