题解:P14732 [ICPC 2022 Seoul R] Shuffle Game
题意简述
给定序列
最长公共子序列(LCS):元素不需要连续,但相对先后顺序必须保持一致。
数据范围:
题目分析
如果暴力生成全部合并后的
状态设计
设
为什么保存最小下标?
同样是长度为
预处理 \operatorname{nxt} 数组
-
不选取
P_2[j] ,继承上一状态:dp[i][j][L] \gets \min(dp[i][j][L], dp[i][j-1][L]) -
使用
P_1[i] 进行匹配。若t = dp[i-1][j][L] \ne \text{INF} ,查询得到新位置\mathit{newpos} :dp[i][j][L+1] \gets \min(dp[i][j][L+1], \mathit{newpos}) -
使用
P_2[j] 进行匹配,逻辑同上:dp[i][j][L+1] \gets \min(dp[i][j][L+1], \mathit{newpos})
初始条件与答案
初始条件:
复杂度分析
预处理
注意:三维数组一定要写在全局,写在
main函数内部会栈溢出导致 RE。
题醒:本人已错不知多少次,代码仅供参考。(题解由本人和家人研究而出,可能有错误和逻辑不对的地方,请以题目为基准。)
代码
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <unordered_map>
using namespace std;
const int MAXN = 505;
const int INF = 1e9;
vector<unordered_map<string, int>> nxt;
int dp[MAXN][MAXN][MAXN];
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, p, q;
cin >> n >> p >> q;
vector<string> X(n + 1);
for (int i = 1; i <= n; ++i)
cin >> X[i];
vector<string> P1(p + 1);
for (int i = 1; i <= p; ++i)
cin >> P1[i];
vector<string> P2(q + 1);
for (int i = 1; i <= q; ++i)
cin >> P2[i];
nxt.resize(n + 2);
unordered_map<string, int> mp;
for (int pos = n; pos >= 0; --pos)
{
if (pos + 1 <= n)
{
mp[X[pos + 1]] = pos + 1;
}
nxt[pos] = mp;
}
for (int i = 0; i <= p; ++i)
for (int j = 0; j <= q; ++j)
for (int l = 0; l <= n; ++l)
dp[i][j][l] = INF;
dp[0][0][0] = 0;
for (int i = 0; i <= p; ++i)
{
for (int j = 0; j <= q; ++j)
{
if (i == 0 && j == 0) continue;
if (i > 0)
{
for (int len = 0; len <= n; ++len)
{
dp[i][j][len] = min(dp[i][j][len], dp[i - 1][j][len]);
}
}
if (j > 0)
{
for (int len = 0; len <= n; ++len)
{
dp[i][j][len] = min(dp[i][j][len], dp[i][j - 1][len]);
}
}
if (i > 0)
{
for (int len = 0; len < n; ++len)
{
int t = dp[i - 1][j][len];
if (t == INF) continue;
string c = P1[i];
if (nxt[t].count(c))
{
int newpos = nxt[t][c];
dp[i][j][len + 1] = min(dp[i][j][len + 1], newpos);
}
}
}
if (j > 0)
{
for (int len = 0; len < n; ++len)
{
int t = dp[i][j - 1][len];
if (t == INF) continue;
string c = P2[j];
if (nxt[t].count(c))
{
int newpos = nxt[t][c];
dp[i][j][len + 1] = min(dp[i][j][len + 1], newpos);
}
}
}
}
}
int ans = 0;
for (int l = n; l >= 0; --l)
{
if (dp[p][q][l] < INF)
{
ans = l;
break;
}
}
cout << ans << endl;
return 0;
}
AI 贡献说明:
题解使用 AI 排版润色。核心思路、推导过程、代码均为个人完成。