LigntOj1422 Halloween Custumes

题意:n天,每天穿哪件衣服有要求,衣服可以套着穿,但是脱下来的衣服就不能再穿了,问最少要准备多少件衣服

题解:这是到区间DP,也算是我的第一道区间DP

   F[ i ][ j ] 表示从第 i 天到第 j 天最少要几件衣服。

   倒着推,我们考虑需不需要第 ai 件衣服,有两种情况:① 需要,那么F[ i ][ j ] = F[ i + 1][ j ] + 1; ② 不需要,那么就在 i + 1 到 j 天找有没有和第 i 天穿的衣服一样的,有那么 F[ i ][ j ] = F[ i + 1][ k ] + F[ k + 1 ][ j ]; 然后来年两者取小的。答案是F[ 1 ][ n ];

CODE:

/*
Author: JDD
PROG: lightoj1422 Halloween Costumes
DATE: 2015.10.8
*/

#include <cstdio>
#define REP(i, s, n) for(int i = s; i <= n; i ++)
#define REP_(i, s, n) for(int i = n; i >= s; i --)
#define MAX_N 105

using namespace std;

int read()
{
    char c = getchar();
    while(!(c >= '0' && c <= '9')) c = getchar();
    int ret = 0;
    while(c >= '0' && c <= '9') ret = ret * 10 + c - '0', c = getchar();
    return ret;
}

int n, a[MAX_N], F[MAX_N][MAX_N];

void init()
{
    n = read();    
    REP(i, 1, n) a[i] = read();
}

#define min(a, b) (a < b ? a : b)

void doit()
{
    REP(i, 1, n) REP(j, 1, n){
        if(i == j) F[i][j] = 1;
        else F[i][j] = 0;
    }
    REP(i, 1, n) REP(j, i + 1, n){
        F[i][j] = F[i][j - 1] + 1;
        REP(k, i, j - 1)
            if(a[j] == a[k]) F[i][j] = min(F[i][j], F[i][k] + F[k + 1][j - 1]);
    }
    printf("%d\n", F[1][n]);
}

int main()
{
    int T; scanf("%d", &T);
    REP(i, 1, T){
        init();
        printf("Case %d: ", i);
        doit();
    }
}

 

posted @ 2015-10-08 19:52  ALXPCUN  阅读(376)  评论(0编辑  收藏  举报