专栏文章
阿尔忒弥西娅的「纯情」
P13866题解参与者 4已保存评论 3
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 3 条
- 当前快照
- 1 份
- 快照标识符
- @minq45fz
- 此快照首次捕获于
- 2025/12/02 06:31 3 个月前
- 此快照最后确认于
- 2025/12/02 06:31 3 个月前
笑点解析:这次的博客标题仍然是一个人的名字。
看不懂哥们我写爆搜的。
有一个很简单的搜索,就是你假装一开始是空栈,然后正常搜,每次在空栈的时候决策要不要在一开始的栈中塞入元素,记得如果之前在空栈的时候不塞元素的话,这里就不能塞之前那个点邻接点里有的点。
然后你发现过不了,你写个记忆化把当前节点和栈和 ban 点直接全部塞进去,还是过不了,容易发现 BUG 主要是这个栈的大小可能会搜得很大,但是如果超过了 就没意义了(实际判 也能过),所以你直接判栈大小超过 就退出,然后就过了,比大多数 dp 跑得快。
upd:最新研究表明不判也能过。
代码:
CPP#include <bits/extc++.h>
using namespace std;
int n, m, k;
int mp[55][25];
int num, T[55][25];
struct dinner {
int S[105], Top;
int size() { return Top; }
void push(int x) { S[Top++] = x; }
void pop() { S[--Top] = 0; }
int top() { return S[Top - 1]; }
} stk;
int ans;
__gnu_pbds::gp_hash_table<unsigned long long, int> dp, vis;
unsigned long long base = 999983;
//
int dfs(int cur, int now) {
if (cur == n) {
ans = min(ans, now);
return 0;
}
if (now >= ans) return 1e9;
if (stk.Top > m) return 1e9;
unsigned long long has = cur;
for (int i = 0; i <= m; i++) {
has = has * base + stk.S[i]; //
}
for (int i = 1; i <= k; i++) { //
if (T[num][i])
has = has * base + 1;
else
has = has * base;
}
if (dp.find(has) != dp.end()) {
ans = min(ans, now + dp[has]);
return dp[has]; //
}
if (vis[has]) return 1e9;
vis[has] = true;
int nxt = 1e9;
if (stk.size() && mp[cur][stk.top()] > -1) {
int tmp = stk.top();
stk.pop();
nxt = min(dfs(mp[cur][tmp], now), nxt);
stk.push(tmp);
} else {
if (!stk.size())
for (int i = 1; i <= k; i++)
if (mp[cur][i] > -1) T[num][i]++;
for (int i = 1; i <= k; i++) {
if (mp[cur][i] > -1) {
stk.push(i);
nxt = min(dfs(mp[cur][i], now), nxt);
stk.pop();
}
}
if (!stk.size())
for (int i = 1; i <= k; i++)
if (mp[cur][i] > -1) T[num][i]--;
if (!stk.size()) {
for (int i = 1; i <= k; i++) {
if (mp[cur][i] > -1 && !T[num][i]) { //
num++;
nxt = min(dfs(mp[cur][i], now + 1) + 1, nxt);
num--;
}
}
}
}
vis[has] = false;
return dp[has] = nxt;
}
int main() {
// freopen("nihility.in","r",stdin);
// freopen("nihility.ouy","w",stdout);
scanf("%d%d%d", &n, &m, &k);
memset(mp, -1, sizeof(mp));
for (int i = 1; i <= m; i++) {
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
u++, v++, w++;
mp[u][w] = v;
}
ans = n - 1;
dfs(1, 0);
printf("%d\n", ans);
return 0;
}
相关推荐
评论
共 3 条评论,欢迎与作者交流。
正在加载评论...