题目大意: 给你n天要穿的衣服,可以套着穿,但是一旦脱下来就不能载穿了,问n天至少需要多少衣服?
做了两个关于区间dp的题,遇到这个题还是不会做,网上搜了一下,感觉也不难,就是自己想不起来。。。
思路:dp[i][j]表示从第i天到第j天至少需要多少衣服,那么dp[i][j] = dp[i + 1][j] + 1,这是最坏情况,就是最多的一种,如果后面有跟第i个相同的,那么根本不许要这么多,只需要dp[i+1][j]中就够了,不用加这个1了,因为后面有跟他相同的,考虑第k天,那么就假设第k天与第i天相同,那么dp[i+1][j]就可以表示为dp[i+1][k-1] + dp[k][j], dp[i + 1][k - 1]表示从i+1天到k-1天最小需要,因为这个和k无关,所以不用管里面有没有相同的,但是后面这个dp[k][j]就有用了,就是说必须k天的跟i天的相同才可以这么拆,不然不能拆。所以状态转移方程就有了。dp[i][j]=min(dp[i][j], dp[i + ][k - 1] + dp[k][j]);
代码如下:
#include <cstdio> #include <iostream> #include <algorithm> using namespace std; const int maxn = 110; const int inf = (1 << 30); int dp[maxn][maxn]; int a[maxn]; int main() { int T, n, kase = 0; scanf("%d", &T); while (T--) { scanf("%d", &n); for (int i = 1; i <= n; i++) scanf("%d", &a[i]); for (int i = 1; i <= n; i++)//初始化 for (int j = i; j <= n; j++) dp[i][j] = j - 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", ++kase, dp[1][n]); } return 0; }