Modern Art 3 (USACO Gold 2021 February)

Modern Art 3 (USACO Gold 2021 US Open)

要仔细分析最优画法的特性。初看这个结构比较像一个堆栈,上层的颜色盖住下层的,但堆栈在这里用起来应该不方便,因为一种颜色可能出现一次,二次,或者任意多次。

回到问题本身,我们要求的东西其实比较简单,只是要画的最少次数。从次数角度考虑,一个最优的画法有以下特点:

例如:

        1
      4---4
    3-------3
  2-----------2
1---------------1 6
       K=4

所以可以认为每有一条这样的线,就是节省一次。我们使用range DP合并两段连续子序列需要画的次数为一段,只需要当大的序列的左右端点是同一个数字的时候,合并时总需要的次数减一就可以了。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
 
int n;
int a[305];
int dp[305][305];
 
int main() {
    scanf("%d", &n);
    for (int i = 0; i < n; i++)
        scanf("%d", &a[i]);
    
    for (int j = 0; j < n; j++) {
        for (int i = 0; i < n-j; i++) {
            if (j == 0) {
                dp[i][i+j] = 1;
                continue;
            }
            dp[i][i+j] = n;
            for (int k = i; k < i+j; k++) {
                // [i,k], [k+1,i+j]
                dp[i][i+j] = min(dp[i][i+j], dp[i][k] + dp[k+1][i+j] 
                                 - (a[i]==a[i+j] ? 1 : 0));
            }
        }
    }
    printf("%d", dp[0][n-1]);
    return 0;
}