题目链接:传送门
题目大意:要参加聚会,对应聚会要穿对应衣服,衣服可以套着穿,也可以脱下来,但脱下来之后不能再穿,问参加完所有聚会至少需要几件衣服?
题目思路:区间DP
一开始自己没有想出来状态转移方程,但是想到了左右区间如果边界相等的时候衣服数目应该-1,可以少穿一件。其实拓展一点就是更新
方程的一部分了。对于区间 [l,r] ,如果r处的值==l处的值(要求穿的衣服相同),那么区间 [l,r]所穿的最少衣服等于区间 [l,r-1] 所穿最少衣服,
因为 l 是起点,也就是说最里面穿的衣服是 l 对应的值,从 l 到 r 无论怎么更新,最里面的那件衣服始终不用脱掉,那么到 r 时候,至少有一种
情况,也就是脱其他所有衣服,只剩 l 时,这时候也是满足条件的。对应的转移的方程 if(a[l]==a[r]) dp[l][r]=dp[l][r-1];
然后对于其他区间,也就相同于普通区间DP转移。
#include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <algorithm> #include <cstring> #include <stack> #include <cctype> #include <queue> #include <string> #include <vector> #include <set> #include <map> #include <climits> #define lson root<<1,l,mid #define rson root<<1|1,mid+1,r #define fi first #define se second #define ping(x,y) ((x-y)*(x-y)) #define mst(x,y) memset(x,y,sizeof(x)) #define mcp(x,y) memcpy(x,y,sizeof(y)) using namespace std; #define gamma 0.5772156649015328606065120 #define MOD 1000000007 #define inf 0x3f3f3f3f #define N 100005 #define maxn 100005 typedef pair<int,int> PII; typedef long long LL; int n,m,a[105],dp[105][105]; int main(){ int i,j,group,Case=0; scanf("%d",&group); while(group--){ mst(dp,inf); scanf("%d",&n); for(i=1;i<=n;++i){ scanf("%d",&a[i]); dp[i][i]=1; } for(int p=2;p<=n;++p) for(int i=1;i<n;++i){ j=i+p-1; if(j>n)break; if(a[i]==a[j])dp[i][j]=dp[i][j-1]; ///*** for(int k=i;k<j;++k){ dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]); ///这里如果a[k]==a[k+1]不需要处理 ///因为在转移之前已经处理过了 } } printf("Case %d: %d\n",++Case,dp[1][n]); } return 0; }
时间: 2024-10-26 10:22:32