Codeforces Round #336 (Div. 2) D. Zuma(区间DP)

题目链接:https://codeforces.com/contest/608/problem/D

题意:给出n个宝石的颜色ci,现在有一个操作,就是子串的颜色是回文串的区间可以通过一次操作消去,问最少需要多少次操作可以消除所有的宝石。(每次操作消除一个回文串,最少操作次数清楚字符串)

题解:dp[l][r]表示区间(l,r)的最少操作次数,对于一个区间(l,r),有两种转移:①若存在c_l = c_i(l <= i <= r),可以由dp[l][i] + dp[i + 1][r]转移;②若c_l = c_r,可以由dp[l + 1][r - 1]转移。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long
 4 #define ull unsigned long long
 5 #define mst(a,b) memset((a),(b),sizeof(a))
 6 #define mp(a,b) make_pair(a,b)
 7 #define pi acos(-1)
 8 #define pii pair<int,int>
 9 #define pb push_back
10 #define lowbit(x) ((x)&(-x))
11 const int INF = 0x3f3f3f3f;
12 const double eps = 1e-6;
13 const int maxn = 510 + 10;
14 const int maxm = 1e6 + 10;
15 const ll mod =  998244353;
16 
17 int c[maxn];
18 int dp[maxn][maxn];
19 
20 int main() {
21 #ifdef local
22     freopen("data.txt", "r", stdin);
23 //    freopen("data.txt", "w", stdout);
24 #endif
25     int n;
26     scanf("%d",&n);
27     for(int i = 0; i < n; i++) {
28         scanf("%d",&c[i]);
29         dp[i][i] = 1;
30     }
31     for(int i = 0; i < n - 1; i++) {
32         if(c[i] == c[i + 1]) dp[i][i + 1] = 1;
33         else dp[i][i + 1] = 2;
34     }
35     for(int i = 2; i < n; i++) {
36         for(int j = 0; i + j < n; j++) {
37             dp[j][j + i] = i + 1;
38             for(int k = j; k < j + i; k++) {
39                 if(c[j] == c[k]) dp[j][j + i] = min(dp[j][j + i], dp[j][k] + dp[k + 1][j + i]);
40             }
41             if(c[j] == c[j + i]) dp[j][j + i] = min(dp[j][j + i], dp[j + 1][j + i - 1]);
42         }
43     }
44     printf("%d\n",dp[0][n - 1]);
45     return 0;
46 }

猜你喜欢

转载自www.cnblogs.com/scaulok/p/10668147.html