window.cnblogsConfig = {//可以放多张照片,应该是在每一个博文上面的图片,如果是多张的话,那么就随机换的。 homeTopImg: [ "https://cdn.luogu.com.cn/upload/image_hosting/xkzro04i.png" ], }

AtCoder ABC 301 复盘

A Overall Winner

AC Code

B Fill the Gaps

AC Code

C AtCoder Cards

这是一道贪心。先统计字符出现的个数,然后尝试用出现次数最少的字符的卡片去替换 @。这个策略可以被证明是正确的。

AC Code

D Bitmask

第一眼看到这道题,我就想暴力枚举,直到我看见了这个:

$$1\leq N\leq 10^{18}$$

于是我们想到了如下思路:

如果把 $S$ 中的每个 ? 都改成 0,答案就是 -1。否则,你可以对每一个被改为 0 的数字从高位到低位做这样的运算:如果将该数字改为 1 不会使数字超过 $N$,则将其改为 1

这是正确的,时间复杂度 $O(\text{字符串}\ S\ \text{的长度})$。

AC Code

E Pac-Takahashi

看到

At most $18$ pairs $(i,j)$ satisfy $A_{i,j}=$ o.

我就想到了暴搜状压 DP。

这里我们先跑 $m$ 遍 $O(n)$ 的 BFS 求出从每个糖果出发到每个点的最短路。然后开逝!

  1. 初始化。初始状态为 $dp_{i,j}=$ INF,$dp_{2^i,i}=d_{i,sx,sy}\ (0\leq i\leq m)$,这里 $m$ 指糖果的个数,$(sx,sy)$ 指出发点,$d_{i,j,k}$ 指从第 $i$ 个糖果出发至 $(sx,sy)$ 的最短距离。

  2. 转移。转移方程如下:

for(int s = 1; s < (1 << m); ++s)
  for(int k = 0; k < m; ++k)
      if(dp[s][k] != 0x3f3f3f3f)
          for(int nx = 0; nx < m; ++nx) {
              if(s >> nx & 1)
                  continue;
              dp[s | 1 << nx][nx] = min(dp[s | 1 << nx][nx], dp[s][k] + d[k][ls[nx].first][ls[nx].second]);
          }

($\LaTeX$ 太难写了,直接贴代码)

  1. 求解。如下:
bfs(sx, sy);
if(dis[gi][gj] <= T)
  ans = 0;
for(int s = 1; s < (1 << m); ++s)
  for(int k = 0; k < m; ++k)
      if(dp[s][k] + d[k][gi][gj] <= T) {
          int now = 0;
          for(int i = 0; i < m; ++i)
              if(s >> i & 1)
                  ++now;
          ans = max(ans, now);
      }

AC Code

posted @ 2024-01-16 19:59  TigerTanWQY  阅读(34)  评论(0)    收藏  举报  来源