dp[i][j]表示第i天到第j天达到的最小值;
因为前面某一天的选择对后面会造成影响,对于这样的问题,我们从后往前dp;
转移方程:
(1) 第i天和[i+1,j]天里的衣服都不同,dp[i][j]=dp[i+1][j]+1;
(2) 第i天和第k天,i+1<=k<=j,存在相同的,那么如果第i天的衣服留下,第k天就可以不加新衣服了,
此时:dp[i][j]=min(dp[i+1][k-1]+dp[k][j],dp[i][j]);
因为第k天要用第i天的内容,所以[i+1,k-1]天的衣服都要脱去;[k,j]是一个独立的部分
#include<string>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int num=110;
int dp[num][num];
int a[num];
int main()
{
int t;
scanf("%d",&t);
for(int s=1;s<=t;s++)
{
memset(dp,0,sizeof(dp));
int n=0;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
for(int i=1;i<=n;i++)
dp[i][i]=1;
for(int i=n-1;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[i]==a[k])
dp[i][j]=min(dp[i][j],dp[i+1][k-1] + dp[k][j]);
}
}
}
printf("Case %d: %d\n",s,dp[1][n]);
}
return 0;
}
#include<string>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
const int num=110;
int dp[num][num];
int a[num];
int dfs(int L,int R)
{
if(L>R) return 0;
if(L==R) return dp[L][R]=1;
if(dp[L][R]!=-1) return dp[L][R];
dp[L][R]=dfs(L,R-1)+1;
for(int k=L;k<R;k++)
{
if(a[k]==a[R])
dp[L][R]=min(dp[L][R],dfs(L,k)+dfs(k+1,R-1));
}
return dp[L][R];
}
int main()
{
int t;
scanf("%d",&t);
for(int s=1;s<=t;s++)
{
memset(dp,-1,sizeof(dp));
int n=0;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
dfs(1,n);
printf("Case %d: %d\n",s,dp[1][n]);
}
return 0;
}