1. 程式人生 > >Halloween Costumes LightOJ - 1422 區間dp

Halloween Costumes LightOJ - 1422 區間dp

題解

題目大意 一個人參加舞會 第i個舞會需要穿著a[i]顏色的衣服 他可以同時穿著多件衣服到時候再脫掉 但是脫掉的衣服不能在穿上 問最少需要多少衣服

使用區間dp求解 d[i][j]表示從i到j區間的舞會需要的最少衣服數量 考慮
單獨一個舞會需要的數量為1
如果一個區間d[i][j] a[i]==a[j]也就是第一場舞會的和最後一場的衣服一樣則d[i][j]一定等於d[i][j - 1]因為最後一個一定能穿第一場的衣服 第一場的衣服全程也不會脫掉 因為他前面沒衣服了脫掉無意義 即d[i][j] = d[i][j - 1]
最後遍歷區間中間點合併區間d[i][j] = min(d[i][j], d[i][k] + d[k + 1][j])

AC程式碼

#include <stdio.h>
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int INF = 0x3f3f3f3f;
const int MAXN = 110;
int a[MAXN];
int d[MAXN][MAXN];

int main()
{
#ifdef LOCAL
	freopen("C:/input.txt", "r", stdin);
#endif
	int T;
	cin >> T;
	for (int ti =
1; ti <= T; ti++) { int N; cin >> N; for (int i = 1; i <= N; i++) scanf("%d", &a[i]); memset(d, 0x3f, sizeof(d)); for (int i = 1; i <= N; i++) d[i][i] = 1; //單個為1 for (int l = 2; l <= N; l++) for (int i = 1; i + l - 1 <= N; i++) { int j = i + l - 1
; if (a[i] == a[j]) //區間前後相等 最後一個一定不會造成貢獻 d[i][j] = d[i][j - 1]; //從小區間轉移過來 第一件不可能脫掉 最後一個肯定可以用第一件 for (int k = i; k < j; k++) //合併區間 d[i][j] = min(d[i][j], d[i][k] + d[k + 1][j]); } printf("Case %d: %d\n", ti, d[1][N]); } return 0; }