P4170

P4170

考虑区间dp

使用我最喜欢的记忆化搜索。。。

首先考虑 \(l == r\) 的情况,答案是 \(dp[l][r] = 1\)

如果区间距离大于 \(1\) 时:

\(s[l] == s[r]\) \(f[l][r] = min(f[l + 1][r],f[l][r - 1],f[l + 1][r - 1] + 1)\) (刷 \(s[l]\) 时,当拓展到 \(s[r]\) 处时不用再加一了)

\(s[l] \not= s[r]\) \(f[l][r] = min(f[l][r],f[l][k] + f[k + 1][r])\)

下面详细说明一下上面的转移方程:

考虑合并时时怎么刷的次数变多的,如 \(pos_A = l\)\(dp[l][k]\) 里面刷过了,那么如果 \(pos_A = r\) 也在 \(dp[k+1][r]\) 中这样合并时必然会多刷一次,在 \(dp[l][r]\) 中只需要刷一次就可以把这两个 \(A\) 都能刷到。

同时因为 \(A\) 时在这个区间的两端所以从 \(L\sim R\)\(A\) 对后面的刷法是不会影响其最优性的。

#include <bits/stdc++.h>
#define SZ(X) ((int)(X).size())
#define ALL(X) (X).begin(), (X).end()
#define rep(I, N) for (int I = 1; I <= (N); ++I)
#define repp(I, N) for (int I = 0; I < (N); ++I)
#define FOR(I, A, B) for (int I = (A); I <= (B); ++I)
#define FORR(I, A, B) for (int I = (A); I >= (B); I--)
#define SORT_UNIQUE(c) (sort(c.begin(),c.end()), c.resize(distance(c.begin(),unique(c.begin(),c.end()))))
#define GET_POS(c,x) (lower_bound(c.begin(),c.end(),x)-c.begin())
#define MP make_pair
#define PB push_back
#define MS0(X) memset((X), 0, sizeof((X)))
#define MS1(X) memset((X), -1, sizeof((X)))
#define LEN(X) strlen(X)
#define F first
#define S second
using namespace std;
const int N = 1000 + 5;
const double eps = 1e-7;
const int mod = 1e9 + 7;
typedef long long LL;
typedef unsigned long long ULL;
typedef long double LD;
typedef pair<int,int> PII;
typedef vector<int> VI;
typedef vector<LL> VL;
typedef vector<PII> VPII;
typedef pair<LL,LL> PLL;
typedef vector<PLL> VPLL;
LL gcd(LL a,LL b){return b>0?gcd(b,a%b):a;}
LL ksm(LL a,LL b){LL ans = 1;while(b){if(b&1) ans = ans * a % mod;a = a * a % mod;b >>= 1;}return ans % mod;}
char s[N];
int n;
int dp[N][N];
int dfs(int l,int r)
{
    if(dp[l][r] != 0x3f3f3f3f)
        return dp[l][r];
    if(l == r) return dp[l][r] = 1;
    int ans = 1e9;
    for (int k = l;k < r;k ++)
    {
        if(s[l] == s[r])
        {
            ans = min(ans,dfs(l + 1,r));
            ans = min(ans,dfs(l,r - 1));
            ans = min(ans, dfs(l + 1, r - 1) + 1);
        }
        else 
        {
            ans = min(ans, dfs(l, k) + dfs(k + 1, r));
        }
    }
    return dp[l][r] = ans;
}
int main() {
    scanf("%s", s + 1);
    n = strlen(s + 1);
    memset(dp, 0x3f, sizeof dp);
    cout << dfs(1, n) << endl;
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/strategist-614/p/12563187.html