[Codeforces Round #667 (Div. 3)]-F. Subsequences of Length Two(动态规划)
[Codeforces Round #667 (Div. 3)]-F. Subsequences of Length Two(动态规划)
链接:https://codeforces.com/contest/1409/problem/F
题面:
题意:
给你两个字符串,分别是\(s,t\) ,其中
s的长度为n,
t的长度为2。
你可以对字符串\(\mathit s\) 做不超过\(\mathit k\) 次操作,每一次操作可以选择字符串中任意一个字符然后将其变成任意一个字符。
问在最优的操作后,有多少个\(\mathit s\) 的子序列为字符串\(\mathit t\)。
思路:
考虑动态规划解决本问题,
状态:
\(dp[i][j][cnt_0]\)代表字符串\(\mathit s\) 的前\(\mathit i\) 个字符中更改了\(\mathit j\) 个字符以至于这\(\mathit i\) 个字符中有\(cnt_0\)个 \(t_0\)字符时,字符串\(\mathit t\)作为子序列出现的最多次数。
设三个额外的变量方便我们转移:
\(e_0\)代表\([s_i=t_0]\),
\(e_1\)代表\([s_i=t_1]\),
\(e_{01}\)代表\([t_0=t_1]\)。
考虑转移:
每一步最优的选择一定是这\(\text 3\) 个选择中的一个:
1、不改变\(s_i\)字符,
那么转移为:\(dp[i+1][j][cnt_0+e_0]=max(dp[i+1][j][cnt_0+e_0],dp[i][j][cnt0] + (e_1 ? cnt_0 : 0))\)
2、\(s_i\)变为\(t_0\)(如果\(s_i\)本来就等于\(t_0\)也无妨,因为这样不会影响答案的正确性),
那么转移为:\(dp[i + 1][j + 1][cnt_0 + 1] = max(dp[i + 1][j + 1][cnt_0 + 1], dp[i][j][cnt_0] + (e_{01} ? cnt_0 : 0))\)
3、\(s_i\) 改变为\(t_1\)。
转移为:\(dp[i + 1][j + 1][cnt_0 + e_{01}] = max(dp[i + 1][j + 1][cnt_0 + e_{01}], dp[i][j][cnt_0] + cnt_0)\)
注意,后两种转移的限制是\(j<k\)。
答案就是\(\max\limits_{ck=0}^{k} \max\limits_{cnt_0=0}^{n} dp_{n, ck, cnt_0}\)
代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <bits/stdc++.h>
#define ALL(x) (x).begin(), (x).end()
#define sz(a) int(a.size())
#define rep(i,x,n) for(int i=x;i<n;i++)
#define repd(i,x,n) for(int i=x;i<=n;i++)
#define pii pair<int,int>
#define pll pair<long long ,long long>
#define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define MS0(X) memset((X), 0, sizeof((X)))
#define MSC0(X) memset((X), '\0', sizeof((X)))
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define eps 1e-6
#define chu(x) if(DEBUG_Switch) cout<<"["<<#x<<" "<<(x)<<"]"<<endl
#define du3(a,b,c) scanf("%d %d %d",&(a),&(b),&(c))
#define du2(a,b) scanf("%d %d",&(a),&(b))
#define du1(a) scanf("%d",&(a));
using namespace std;
typedef long long ll;
ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
ll lcm(ll a, ll b) {return a / gcd(a, b) * b;}
ll powmod(ll a, ll b, ll MOD) { if (a == 0ll) {return 0ll;} a %= MOD; ll ans = 1; while (b) {if (b & 1) {ans = ans * a % MOD;} a = a * a % MOD; b >>= 1;} return ans;}
ll poww(ll a, ll b) { if (a == 0ll) {return 0ll;} ll ans = 1; while (b) {if (b & 1) {ans = ans * a ;} a = a * a ; b >>= 1;} return ans;}
void Pv(const vector<int> &V) {int Len = sz(V); for (int i = 0; i < Len; ++i) {printf("%d", V[i] ); if (i != Len - 1) {printf(" ");} else {printf("\n");}}}
void Pvl(const vector<ll> &V) {int Len = sz(V); for (int i = 0; i < Len; ++i) {printf("%lld", V[i] ); if (i != Len - 1) {printf(" ");} else {printf("\n");}}}
inline long long readll() {long long tmp = 0, fh = 1; char c = getchar(); while (c < '0' || c > '9') {if (c == '-') fh = -1; c = getchar();} while (c >= '0' && c <= '9') tmp = tmp * 10 + c - 48, c = getchar(); return tmp * fh;}
inline int readint() {int tmp = 0, fh = 1; char c = getchar(); while (c < '0' || c > '9') {if (c == '-') fh = -1; c = getchar();} while (c >= '0' && c <= '9') tmp = tmp * 10 + c - 48, c = getchar(); return tmp * fh;}
void pvarr_int(int *arr, int n, int strat = 1) {if (strat == 0) {n--;} repd(i, strat, n) {printf("%d%c", arr[i], i == n ? '\n' : ' ');}}
void pvarr_LL(ll *arr, int n, int strat = 1) {if (strat == 0) {n--;} repd(i, strat, n) {printf("%lld%c", arr[i], i == n ? '\n' : ' ');}}
const int maxn = 205;
const int inf = 0x3f3f3f3f;
/*** TEMPLATE CODE * * STARTS HERE ***/
#define DEBUG_Switch 0
int n;
int k;
char s[maxn];
char t[maxn];
int main()
{
#if DEBUG_Switch
freopen("C:\\code\\input.txt", "r", stdin);
#endif
//freopen("C:\\code\\output.txt","w",stdout);
cin >> n >> k;
cin >> s;
cin >> t;
std::vector<vector<vector<int> > > dp(n + 1, vector<vector<int>>(n + 1, vector<int>(n + 1, -inf)));
dp[0][0][0] = 0;
repd(i, 0, n - 1)
{
repd(j, 0, k)
{
repd(cnt0, 0, n)
{
if (dp[i][j][cnt0] == -inf)
continue;
int e0 = s[i] == t[0];
int e1 = s[i] == t[1];
int e01 = t[0] == t[1];
dp[i + 1][j][cnt0 + e0] = max(dp[i + 1][j][cnt0 + e0], dp[i][j][cnt0] + (e1 ? cnt0 : 0));
if (j < k)
{
dp[i + 1][j + 1][cnt0 + 1] = max(dp[i + 1][j + 1][cnt0 + 1], dp[i][j][cnt0] + (e01 ? cnt0 : 0));
dp[i + 1][j + 1][cnt0 + e01] = max(dp[i + 1][j + 1][cnt0 + e01], dp[i][j][cnt0] + cnt0);
}
}
}
}
int ans = 0;
repd(j, 0, k)
{
repd(cnt0, 0, n)
{
ans = max(ans, dp[n][j][cnt0]);
}
}
printf("%d\n", ans);
return 0;
}