Luogu 3638 [APIO 2013] 机器人

2023-05-16

          • 传送门
          • 思路
          • 正解
          • 参考代码
          • 关于 SPFA

传送门
思路

   n n 这么小,会不会是搜索题?稍有经验的我直接否定了这个结论 = =。仔细读题并分析样例,发现原来一个位置可以有多个机器人,且机器人行走的时候无视其它机器人,那这个就是一张图啊。可以将这张图预处理出来,则问题变为把所有机器人在某个结点合并的路径长度之和的最小值。

  我本以为跑个多源 BFS 就好了,但是猛然发现机器人合并后步数会改变,然后我就凉了……

正解

  还是先将整张图预处理出来,注意需要用 DFS 记忆化保证时间复杂度。

  这道题其实是一个动态规划(怎么想到的 = =)。我们设 fl,r,x,y 表示使得 lr l ∼ r 的复合机器人在 (x,y) ( x , y ) 的最小代价,显然边界条件为:

fi,i,xi,yi=0 f i , i , x i , y i = 0

  考虑转移。显然我们可以选择走一步:

fl,k,x,y+fk+1,r,x,yfl,r,x,y f l , k , x , y + f k + 1 , r , x , y → f l , r , x , y
fl,r,x,y+1fl,r,x,y f l , r , x , y + 1 → f l , r , x ′ , y ′

  对于一个位置,我们先用第一个转移计算出自己的最小代价,再用第二个转移去更新别人的最小代价。发现,这个转移的方法与斯坦纳树的做法是十分类似的,但是和斯坦纳树本身毛关系都没有

祸害众生的神仙题解

始作俑者,害得看透这道题的人偏偏也加上了一个斯坦纳树的标签

  是个铲铲!

参考代码

  唉,我太弱了,什么都不会,DFS 一开始写错了,调了一个上午……

(C++ 11 is needed)

#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <cassert>
#include <cctype>
#include <climits>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <stack>
#include <queue>
#include <deque>
#include <map>
#include <set>
#include <bitset>
#include <list>
#include <functional>
#define loop register int
typedef long long LL;
typedef unsigned long long ULL;
using std::cin;
using std::cout;
using std::endl;
typedef int INT_PUT;
INT_PUT readIn()
{
    INT_PUT a = 0; bool positive = true;
    char ch = getchar();
    while (!(ch == '-' || std::isdigit(ch))) ch = getchar();
    if (ch == '-') { positive = false; ch = getchar(); }
    while (std::isdigit(ch)) { a = a * 10 - (ch - '0'); ch = getchar(); }
    return positive ? -a : a;
}
void printOut(INT_PUT x)
{
    char buffer[20]; int length = 0;
    if (x < 0) putchar('-'); else x = -x;
    do buffer[length++] = -(x % 10) + '0'; while (x /= 10);
    do putchar(buffer[--length]); while (length);
}

int INF;
const int maxn = 505;
int n, w, h;
int rect[maxn][maxn];
typedef std::pair<int, int> Point;
Point pos[10];

enum { RIGHT, UP, LEFT, DOWN };
const int vecx[] = { 0, -1, 0, 1 };
const int vecy[] = { 1, 0, -1, 0 };
Point to[maxn][maxn][4];

int vis[maxn][maxn][4];
int stamp;
void DFS(int x, int y, int dir)
{
    if (to[x][y][dir].first)
        return;
    vis[x][y][dir] = stamp;
    int newz = dir;
    if (rect[x][y] == -2)
        newz = (newz + 1) & 3;
    else if (rect[x][y] == -3)
        newz = (newz + 4 - 1) & 3;
    int newx = x + vecx[newz];
    int newy = y + vecy[newz];
    if (!(1 <= newx && newx <= h && 1 <= newy && newy <= w) || rect[newx][newy] == -1)
    {
        to[x][y][dir] = std::make_pair(x, y);
        return;
    }
    else if (vis[newx][newy][newz] == stamp)
    {
        to[x][y][dir] = std::make_pair(-1, -1);
        return;
    }
    DFS(newx, newy, newz);
    to[x][y][dir] = to[newx][newy][newz];
}
void init()
{
    for (loop x = 1; x <= h; x++)
        for (loop y = 1; y <= w; y++)
            for (loop i = 0; i < 4; i++)
            {
                stamp++;
                DFS(x, y, i);
            }
}

int f[10][10][maxn][maxn];
struct Queue
{
    Point c[maxn * maxn];
    int head, tail;
    Queue() { clear(); }
    void clear() { head = tail = 0; }
    void push(const Point& x) { c[tail++] = x; }
    void pop() { head++; }
    Point front() { return c[head]; }
    int val(int l, int r) { return f[l][r][c[head].first][c[head].second]; }
    bool empty() { return head == tail; }
    void sort(int l, int r)
    {
        std::sort(c + head, c + tail,
            [=](const Point& a, const Point& b)
        {
            return f[l][r][a.first][a.second] < f[l][r][b.first][b.second];
        });
    }
} q1, q2;
bool inQ[maxn * maxn];
void SPFA(int l, int r)
{
    q1.clear();
    q2.clear();
    for (loop x = 1; x <= h; x++)
        for (loop y = 1; y <= w; y++)
            if (f[l][r][x][y] < INF)
            {
                q1.push(std::make_pair(x, y));
                inQ[x * w + y] = true;
            }
    q1.sort(l, r);

    while (!(q1.empty() && q2.empty()))
    {
        Point from;
        if (q2.empty() || (!q1.empty() && q1.val(l, r) <= q2.val(l, r)))
        {
            from = q1.front();
            q1.pop();
        }
        else
        {
            from = q2.front();
            q2.pop();
        }
        inQ[from.first * w + from.second] = false;

        for (int i = 0; i < 4; i++)
        {
            const Point& t = to[from.first][from.second][i];
            if (t.first == -1) continue;
            int update = f[l][r][from.first][from.second] + 1;
            int& ans = f[l][r][t.first][t.second];
            if (update < ans)
            {
                ans = update;
                if (!inQ[t.first * w + t.second])
                {
                    q2.push(std::make_pair(t.first, t.second));
                    inQ[t.first * w + t.second] = true;
                }
            }
        }
    }
}
void solve()
{
    memset(f, 0x3f, sizeof(f));
    for (int i = 1; i <= n; i++)
        f[i][i][pos[i].first][pos[i].second] = 0;

    for (int len = 1; len <= n; len++)
    {
        for (int l = 1, r = l + len - 1; r <= n; l++, r++)
        {
            if (len > 1)
                for (loop x = 1; x <= h; x++)
                    for (loop y = 1; y <= w; y++)
                        for (loop i = l; i < r; i++)
                            f[l][r][x][y] = std::min(f[l][r][x][y], f[l][i][x][y] + f[i + 1][r][x][y]);

            SPFA(l, r);
        }
    }

    int ans = INF;
    for (int i = 1; i <= h; i++)
        for (int j = 1; j <= w; j++)
            ans = std::min(ans, f[1][n][i][j]);
    if (ans >= INF)
        printOut(-1);
    else
        printOut(ans);
}

void run()
{
    memset(&INF, 0x3f, sizeof(INF));
    n = readIn();
    w = readIn();
    h = readIn();
    for (int x = 1; x <= h; x++)
    {
        for (int y = 1; y <= w; y++)
        {
            char ch = getchar();
            while (!(std::isdigit(ch) || ch == '.' ||
                ch == 'x' || ch == 'A' || ch == 'C'))
                ch = getchar();
            switch (ch)
            {
            case 'x': rect[x][y] = -1; break;
            case 'A': rect[x][y] = -2; break;
            case 'C': rect[x][y] = -3; break;
            case '.': break;
            default: pos[ch - '0'] = std::make_pair(x, y);
            }
        }
    }

    init();
    solve();
}

int main()
{
    run();
    return 0;
}
关于 SPFA

  这道题我使用两个队列进行 SPFA 而不是一个,同时一开始还排了序,这是因为这样使得这个算法满足 BFS 的性质,即更新后的点不会再次被更新。这意味着时间复杂度为 O(n+m) O ( n + m )

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Luogu 3638 [APIO 2013] 机器人 的相关文章

  • 2013 google校园招聘笔试题

    2013 google校园招聘笔试题 回忆版 xff0c 难免有错误 xff0c 欢迎指正 同时欢迎大家在评论中讨论答案 1 单项选择题 1 1如果把传输速率定义为单位时间内传送的信息量 xff08 以字节计算 xff09 多少 关于一下几
  • ERROR 2013 (HY000): Lost connection to MySQL server at 'reading initial communication packet', syste

    好几天没用MySQL xff0c 今天出现了这个ERROR 2013 HY000 Lost connection to MySQL server at 39 reading initial communication packet 39 s
  • 百度2013校园招聘移动软件研发工程师笔试题(二)

    百度2013校园招聘移动软件研发工程师笔试题 二 第一题 1 xff1a 用C 43 43 JAVA Objective c C 解释 xff0c 怎么实现面向对象特征 2 xff1a 第二小题 xff1a 用Java或C 43 43 编写
  • 我的2013 --那些划过生命线的人和事(大二.上)

    那些划过生命线的人和事 大二 上 又一次大清早被红马甲查赶出被窝 xff0c 让哥光着屁股就跑到隔壁宿舍去了 xff0c 真心恨死他们 这是一篇最早写于 2013 11 26 日的日志 xff0c 通过后来不断地增删改 xff0c 来总结
  • 回首2013,展望2014

    此刻值此2013年末 xff0c 明天便是元旦 近日浏览CSDN论坛时 xff0c 发现有许多的坛友都在写2013年度总结 xff0c 博客作为个人的名片 xff0c 也决定开始尝试写博客 xff0c 我的第一篇博客就是关于2013年度总结
  • 我的2013

    今天是2013年的最后一天 xff0c 天气格外的晴朗 xff0c 站在公司的写字楼上 xff0c 能够看到远处的山水 一直都习惯在一年的最后总结一下 xff0c 总结自己哪些地方在成长 xff0c 哪些地方有收获 xff0c 哪些地方需要
  • 阿里巴巴2014校招笔试题-2013年9月14日

    不得不吐槽 xff0c 阿里真是太混乱了 xff0c 北京的笔试在考场等了两个半小时 xff0c 考卷都没运到考场 xff0c 64 阿里巴巴集团校园招聘 回应说 xff1a 北京的同学们 xff0c 简单解释下 xff0c 为了试卷的保密
  • 再见,2012,你好,2013.

    其实这篇日志过年前 xff0c 已经写得差不多 xff0c 但是忘记发了 xff0c 现在补上 xff0c 现在应该还不是太晚吧 ps xff1a 想了一个很俗的标题 61 61 2012年 xff0c 是对我意义最不平凡的一年 这一年 x
  • Luogu 3632 [APIO 2011] 寻路

    传送门正解参考代码 传送门 正解 暴力连边跑最短路就好了 xff0c 只不过代码太长太难写啦 xff01 参考代码 span class hljs preprocessor include lt cstdio gt span span cl
  • Luogu 1552 [APIO 2012] 派遣

    传送门思路参考代码 传送门 思路 唉 xff0c 我太弱了 xff0c 什么都不会 xff0c 题读错了两次 xff0c 一开始读成了一个一般的背包 xff0c 然后读成了一个价值和花费相同的背包 xff0c 最后才发现原来是一个价值为 1
  • UOJ 2016 [APIO 2016] Gap

    传送门思路参考代码交互题 交互题大致形式Windows 平台下 xff08 Dev C 43 43 xff09 Ubuntu 平台下 传送门 思路 唉 xff0c 我太弱了 xff0c 什么都不会 xff0c 题也做不来 这道题简直就是利用
  • APIO 2018 Practice Session T1 Wedding cake

    没有传送门题目大意思路参考代码熟悉环境 没有传送门 题目大意 给你一个长度为 n n 的正整数序列 a i ai xff0c 要求构造出 n n 个小数 使得它们的和为 1 1 xff0c 且每个数小数点后恰好有
  • APIO 2018 游记

    Day 0Day 1Day 2Day 3Day 4 Day 0 早上 4 4 点就上车去机场赶那 7 7 点的飞机 感觉很困 xff0c 所以在飞机上就这么睡过去了 北京是个好地方 xff0c 但是与我无关 下飞机后 xff0c 我们一行人
  • Luogu 2114 [NOI 2014] 起床困难综合症

    传送门思路参考代码 传送门 思路 按位贪心 但是我太弱了 xff0c 明明可以 O n O n 预处理 xff0c 我却只会 O 32 n O
  • 我的2013,梦在路上

    我的2013 xff0c 在路上 今年最后一次给姐姐打电话 xff0c 她在那里像我炫耀自己和爸爸妈妈一起跨年 xff0c 说1314的意义 xff0c 而我还在北京苦逼着 回想2013年对于我来说 xff0c 或许是不错的一年 这一年我进
  • 小米2013校园招聘笔试题

    题目 xff1a 一个数组里 xff0c 除了三个数是唯一出现的 xff0c 其余的都出现偶数个 xff0c 找出这三个数中的任一个 比如数组元素为 1 2 4 5 6 4 2 xff0c 只有1 5 6这三个数字是唯一出现的 xff0c
  • 百度2013校园招聘移动软件研发工程师笔试题(二)

    百度2013校园招聘移动软件研发工程师笔试题 二 第一题 1 xff1a 用C 43 43 JAVA Objective c C 解释 xff0c 怎么实现面向对象特征 2 xff1a 第二小题 xff1a 用Java或C 43 43 编写
  • 我的2013 --那些划过生命线的人和事(大二.上)

    那些划过生命线的人和事 大二 上 又一次大清早被红马甲查赶出被窝 xff0c 让哥光着屁股就跑到隔壁宿舍去了 xff0c 真心恨死他们 这是一篇最早写于 2013 11 26 日的日志 xff0c 通过后来不断地增删改 xff0c 来总结
  • 我的2013,我的CSDN

    2013年是我写CSDN博客的第三个年头了 xff0c 这一年我的博客访问量直线上升 xff0c 这一年我知道了什么是博客专栏 xff0c 这一年我知道如何申请CSDN专家 虽然失败了 xff0c 这一年我从CSDN博客收获了很多很多 xf
  • 我的2013,梦在路上

    我的2013 xff0c 在路上 今年最后一次给姐姐打电话 xff0c 她在那里像我炫耀自己和爸爸妈妈一起跨年 xff0c 说1314的意义 xff0c 而我还在北京苦逼着 回想2013年对于我来说 xff0c 或许是不错的一年 这一年我进

随机推荐

  • mysql数据库conf配置详解

    mysqld port 61 6033 skip grant tables datadir 61 usr tools mysql data socket 61 usr tools mysql mysql sock user 61 mysql
  • LaTeX 008:比较方便的键入下划线的方式

    在 LaTeX 中 xff0c 我们有时会需要输入下划线 直接键入 是不行的 xff0c 会出现的编译错误 xff0c 正如网友所述 xff0c LaTeX 为了简化对编译错误的处理禁止在文本模式 xff08 text mode xff09
  • LaTeX 009:自定义带有 * 号的命令

    LaTeX 中 xff0c 我们经常见到 section 和 section xff0c 分别表示有编号的 section 和没有编号的 section 我们也想自己定义带有 号的命令 xff0c 但写下面的代码时却报错了 xff1a ne
  • 2022 New Year‘s Resolution

    Some Might Say 2022 New Year 39 s Resolution Some might say we are on the edge of the new era Always are they saying thi
  • C++ 多线程编程导论(中)

    受篇幅限制 xff0c 上半部分不再更新 xff0c 填坑的新内容都放在此文章中 文章目录 参考资料线程安全 xff08 续 xff09 互斥访问 互斥体 xff08 mutex xff09 和锁 xff08 lock xff09 什么是互
  • C++ 使用模板序列化/反序列化固定键值对

    仅是一个原型 xff0c 留作记录 我感觉可以写出非常逆天的代码 span class token macro property span class token directive hash span span class token d
  • 编译原理习题两则(龙书,写出语言的正则定义)

    3 3 5 3 注释 xff0c 即 和 之间的串 xff0c 且串中没有不在双引号 xff08 34 xff09 中的 注 xff1a 假设双引号是匹配的 思路 xff1a 从空串开始写 xff0c 写出整体框架后 xff0c 通过分类讨
  • 2023 New Year‘s Resolution

    This Is Game 2023 New Year 39 s Resolution My 2022 ended with a day of game I am convinced that I am not to blame becaus
  • 补录:2018 和 2019 New Year‘s Resolution

    前言 xff1a 吉光片羽 xff0c 以飨读者 2018 New Year 39 s Resolution One year and a half ago I felt that life in 2020 would be quite d
  • 原博文地址

    由于账号问题 xff0c 现更改为这个账号 xff0c 以下为原博文地址 使用WH MOUSE LL钩子来判断按键是否是mouse event模拟的 http blog csdn net qq 26140973 article detail
  • [NOI 2003] 文本编辑器 Splay 维护序列 / 块状链表

    传送门 xff08 JZOJ xff09 xff08 第一道全国决赛题 xff09 解法 1 xff1a 使用 Splay 维护 不管怎么说 xff0c 总和刚刚学过的迎合上了 这道题可以直接上 Splay 维护线性序列 xff0c 光标位
  • 一次macOS的升级填坑(macOS Catalina - macOS Monterey)

    目录 小序一 升级前操作二 升级中三 问题填坑1 像我一样长时间卡在一个进度条怎么办2 在更新途中重启过电脑 xff08 完整流程填坑 xff09 3 安装之后不能开机 xff0c 如何紧急拷贝资料4 安装不成功 xff0c 如何重新安装系
  • CF 713C Sonya and Problem Wihtout a Legend

    文章目录 传送门题目大意正解通过维护关键点来维护信息参考代码 传送门 题目大意 给定一个长度为 n n 3000
  • Luogu 3642 [APIO 2016] 烟火表演

    传送门引例 xff08 上一道题 xff09 凸函数一开始的思路正解参考代码总结 传送门 引例 xff08 上一道题 xff09 凸函数 回忆我们上一道题是怎么做的 我们维护的东西的实质是一个 xff08 下 xff09 凸函数 由于我们的
  • Luogu 3631 [APIO 2011] 方格染色

    传送门思路参考代码细节 传送门 思路 很不错的一道题 xff0c 用到的东西不深 xff0c 但是要想到确实需要一定思维 一开始我想的是动态规划 xff0c 发现如果要设状态需要知道一个格子左边 xff0c 上边和左上边三个格子的状态 然后
  • Luogu 3632 [APIO 2011] 寻路

    传送门正解参考代码 传送门 正解 暴力连边跑最短路就好了 xff0c 只不过代码太长太难写啦 xff01 参考代码 span class hljs preprocessor include lt cstdio gt span span cl
  • Luogu 3634 [APIO 2012] 守卫

    传送门思路正解参考代码 传送门 思路 感觉自己越来越笨了 首先 xff0c 很明显这道题需要把没有看到忍者的区间给删去 xff0c 可以用前缀和 O n O n 处理 xff0c 然后对没有删去的地方重新标号 重新标号时 xff0c 需要对
  • Luogu 1552 [APIO 2012] 派遣

    传送门思路参考代码 传送门 思路 唉 xff0c 我太弱了 xff0c 什么都不会 xff0c 题读错了两次 xff0c 一开始读成了一个一般的背包 xff0c 然后读成了一个价值和花费相同的背包 xff0c 最后才发现原来是一个价值为 1
  • 贪玩 CF 之旅

    文章目录 CF 7D Palindrome Degree http codeforces com problemset problem 7 D 题解 CF 713C Sonya and Problem Wihtout a Legend ht
  • Luogu 3638 [APIO 2013] 机器人

    传送门思路正解参考代码关于 SPFA 传送门 思路 n n 这么小 会不会是搜索题 稍有经验的我直接否定了这个结论 仔细读题并分析样例 发现原来一个位置可以有多个机器人 且机器人行走的时候无视其它机器人 那这个就是一张图啊 可以将这张图预处