LightOJ - 1422 (区间DP)

题意:有t组数据,对于每组,有n个聚会需要参加,下面依次是参加各个聚会需要的衣服编号,要求所需要的衣服一定穿在外面,在操作的时候,可以选择穿上一件衣服或脱下一件衣服,脱下的衣服不能继续使用,问最少需要的衣服数量。

分析:在穿第j件衣服的时候,我们需要知道原先的状态是否穿着第j件衣服,所以我们需要枚举所有间断的区间,需要用到区间dp

          dp[i][j]代表,从第i个聚会到第j个聚会需要的最少的衣服数量

          dp[i][j]最坏情况是第j件衣服是新穿的,dp[i][j]=dp[i][j-1]+1;

          然后依次枚举k,如果第k件衣服和j件衣服相同

          那么 dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j-1])  (dp[i][k]保证最后一定有第k件衣服给第j次)

代码如下:

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
using namespace std;
#define INF 0x3f3f3f3f
int dp[110][110];
int a[110];
int t,n,Case=0;
int main()
{
    scanf("%d",&t);
    while(t--)
    {
      Case++;
      scanf("%d",&n);
      for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
      for(int i=1;i<=n;i++)
         for(int j=1;j<=n;j++)
      {
         if(i==j)dp[i][j]=1;
          else if(i>j)dp[i][j]=0;
          else dp[i][j]=INF;
      }

   for(int l=1;l<=n-1;l++)
      for(int i=1;i<=n-l;i++)
      {
         int  j=l+i;
          dp[i][j]=dp[i][j-1]+1;
          for(int k=i;k<j;k++)
          {
             if(a[j]==a[k])
             dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j-1]);
          }
      }
      printf("Case %d: %d\n",Case,dp[1][n]);
    }
    return 0;
}

 

posted @ 2018-09-13 10:58  hinata_hajime  阅读(142)  评论(0编辑  收藏  举报