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(); } }