专栏文章

阿尔忒弥西娅的「纯情」

P13866题解参与者 4已保存评论 3

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
3 条
当前快照
1 份
快照标识符
@minq45fz
此快照首次捕获于
2025/12/02 06:31
3 个月前
此快照最后确认于
2025/12/02 06:31
3 个月前
查看原文
笑点解析:这次的博客标题仍然是一个人的名字。
看不懂哥们我写爆搜的。
有一个很简单的搜索,就是你假装一开始是空栈,然后正常搜,每次在空栈的时候决策要不要在一开始的栈中塞入元素,记得如果之前在空栈的时候不塞元素的话,这里就不能塞之前那个点邻接点里有的点。
然后你发现过不了,你写个记忆化把当前节点和栈和 ban 点直接全部塞进去,还是过不了,容易发现 BUG 主要是这个栈的大小可能会搜得很大,但是如果超过了 mm 就没意义了(实际判 nn 也能过),所以你直接判栈大小超过 mm 就退出,然后就过了,比大多数 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 条评论,欢迎与作者交流。

正在加载评论...