Building in Sandbox

本文介绍了一种用于判断玩家在沙盒游戏中按照指定顺序放置方块是否合法的算法。通过正向放置与逆向移除两种策略结合广度优先搜索(BFS),确保新加入的方块既与已有的方块相邻又可达。代码示例展示了具体的实现细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本题来自hihocoder#1291
 
时间限制:30000ms
单点时限:3000ms
内存限制:256MB

描述

Little Hi is playing a sandbox voxel game. In the game the whole world is constructed by massive 1x1x1 cubes. The edges of cubes are parallel to the coordinate axes and the coordinates (x, y, z) of the center of each cube are integers.

At the beginning there is nothing but plane ground in the world. The ground consists of all the cubes of z=0. Little Hi needs to build everything by placing cubes one by one following the rules:

1. The newly placed cube must be adjacent to the ground or a previously placed cube. Two cubes are adjacent if and only if they share a same face.

2. The newly placed cube must be accessible from outside which means by moving in 6 directions(up, down, left, right, forward, backward) there is a path from a very far place - say (1000, 1000, 1000) in this problem - to this cube without passing through ground or other cubes.

Given a sequence of cubes Little Hi wants to know if he can build the world by placing the cubes in such order.

输入

The first line contains the number of test cases T(1 <= T <= 10).

For each test case the first line is N the number of cubes in the sequence.

The following N lines each contain three integers x, y and z indicating the coordinates of a cube.

 

For 20% of the data, 1 <= N <= 1000, 1 <= x, y, z <= 10.

For 100% of the data, 1 <= N <= 100000, 1 <= x, y, z <= 100.

输出

For each testcase output "Yes" or "No" indicating if Little Hi can place the cubes in such order.

样例提示

In the first test case three cubes are placed on the ground. It's OK.

In the second test case (1, 3, 2) is neither on the ground nor adjacent to previous cubes. So it can't be placed.

In the last test case (2, 2, 1) can not be reached from outside. So it can't be placed.  

样例输入

3
3
1 1 1
1 2 1
1 3 1
3
1 1 1
1 2 1
1 3 2
17
1 1 1
1 2 1
1 3 1
2 3 1
3 3 1
3 2 1
3 1 1
2 1 1
2 1 2
1 1 2
1 2 2
1 3 2
2 3 2
3 3 2
3 2 2
2 2 2
2 2 1

样例输出

Yes
No
No

对于这道题,我们需要检测一个方块序列能不能被逐个放置,只需检查两个条件,第一个条件是检查新放入的方块是否与之前放入的方块相邻,这个很容易做到。关键在于第二个条件,我们需要检测新放入的方块能否通往无穷远处。一个基本的想法是使用floodfill,不过如果直接对每个方块使用这个方法的话,我们的算法会超时。一个想法是,我们希望能够动态地维护哪些地方可以通往无穷远处,但是问题在于,我们很难判断一个放入方块的操作是否会导致某一块区域被封闭起来。于是这道题的突破口正在此处,如果我们按顺序往里放方块的话,我们很难判断放入方块是否会封闭住一些区域,但是如果我们考虑一个逆向的过程,往外拿方块呢?每拿一个方块,我们就在拿掉的地方进行一次floodfill,这样我们就能算出拿掉这个方块后我们增加了哪些外部点。同时,我们只需要查看一个方块是否与外部点相邻,就能判断能否拿掉这个方块。容易验证,我们能顺序地放入方块,当且仅当满足相邻条件,且我们可以逆向的拿掉方块。

代码如下:

#include<iostream>
#include<vector>
#include<deque>
#include<stack>
#include<string>
#include<algorithm>
#include<string.h>
#include<sstream>

struct Point {
    int x, y, z;
    Point() : x(0), y(0), z(0) {};
    Point(int a, int b, int c) : x(a), y(b), z(c) {}
};

int MAX_C;
const int MAX_N = 100000+5;
const int dir[6][3] = {
    {1, 0, 0},
    {0, 1, 0},
    {0, 0, 1},
    {-1, 0, 0},
    {0, -1, 0},
    {0, 0, -1}
};


int pos[100 + 2][100 + 2][100 + 2];
int is_out[100 + 2][100 + 2][100 + 2];
Point cors[MAX_N];

using namespace std;


bool has_adj(int x, int y, int z) {
    if (z == 1) return true;

    for (int d = 0; d < 6; ++d) {
        int x1 = x + dir[d][0];
        int y1 = y + dir[d][1];
        int z1 = z + dir[d][2];

        if (pos[x1][y1][z1]) return true;
    }

    return false;
}

bool can_take(int x, int y, int z) {
    for (int d = 0; d < 6; ++d) {
        int x1 = x + dir[d][0];
        int y1 = y + dir[d][1];
        int z1 = z + dir[d][2];

        if (is_out[x1][y1][z1]) return true;
    }

    return false;
}

void my_bfs(int x, int y, int z) {
    deque<Point> q;
    Point p0(x, y, z);
    q.push_back(p0);

    while (!q.empty()) {
        Point p = q[0];
        q.pop_front();

        if (p.z < 1 || p.z > MAX_C + 1 || p.x < 0 || p.x > MAX_C + 1 || p.y < 0 || p.y > MAX_C + 1) continue;
        if (is_out[p.x][p.y][p.z] || pos[p.x][p.y][p.z]) continue;
        

        is_out[p.x][p.y][p.z] = 1;
        for (int d = 0; d < 6; ++d) {
            int x1 = p.x + dir[d][0];
            int y1 = p.y + dir[d][1];
            int z1 = p.z + dir[d][2];

            Point p1(x1, y1, z1);
            q.push_back(p1);
        }
    
    }

}

int main() {
    int T;
    cin >> T;
    for (int t = 0; t < T; ++t) {
        int N;
        cin >> N;
        memset(pos, 0, sizeof(pos));
        memset(is_out, 0, sizeof(is_out));

        bool is_possible = true;
        MAX_C = 0;
        for (int i = 0; i < N; ++i) {
            int x, y, z;
            cin >> x >> y >> z;
            cors[i].x = x;
            cors[i].y = y;
            cors[i].z = z;
            MAX_C = max(x, MAX_C);
            MAX_C = max(y, MAX_C);
            MAX_C = max(z, MAX_C);
            if (!pos[x][y][z] && has_adj(x, y, z)) {
                pos[x][y][z] = 1;
            }
            else {
                is_possible = false;
                //break;
            }
        }

        if (!is_possible) {
            cout << "No" << endl;
            continue;
        }

        else {
            my_bfs(0, 0, 1);

            for (int i = N - 1; i >= 0; --i) {
                int x = cors[i].x;
                int y = cors[i].y;
                int z = cors[i].z;
                if (!can_take(x, y, z)) {
                    is_possible = false;
                    break;
                }
                pos[x][y][z] = 0;
                my_bfs(x, y, z);
            }

            if (is_possible) cout << "Yes" << endl;
            else cout << "No" << endl;
        
        }
    }

    //system("pause");
    return 0;
}

 

转载于:https://www.cnblogs.com/mhkds/p/6919353.html

px4_user@DESKTOP-807L394:~$ sudo apt install code Reading package lists... Done Building dependency tree... Done Reading state information... Done No apt package "code", but there is a snap with that name. Try "snap install code" E: Unable to locate package code px4_user@DESKTOP-807L394:~$ ls\ > ^C px4_user@DESKTOP-807L394:~$ ^C px4_user@DESKTOP-807L394:~$ ls PX4-Autopilot ubuntu-wsl2-systemd-script px4_user@DESKTOP-807L394:~$ cd PX4-Autopilot/ px4_user@DESKTOP-807L394:~/PX4-Autopilot$ ls CMakeLists.txt Jenkinsfile Tools install_geographiclib_datasets.sh posix-configs CODE_OF_CONDUCT.md Kconfig appveyor.yml integrationtests src CONTRIBUTING.md LICENSE boards launch test CTestConfig.cmake Makefile cmake msg test_data Documentation README.md eclipse.cproject package.xml validation Firmware.sublime-project ROMFS eclipse.project platforms px4_user@DESKTOP-807L394:~/PX4-Autopilot$ code . Command 'code' not found, but can be installed with: sudo snap install code px4_user@DESKTOP-807L394:~/PX4-Autopilot$ sudo snap install code error: This revision of snap "code" was published using classic confinement and thus may perform arbitrary system changes outside of the security sandbox that snaps are usually confined to, which may put your system at risk. If you understand and want to proceed repeat the command including --classic. px4_user@DESKTOP-807L394:~/PX4-Autopilot$ sudo snap install code --classic 2025-07-09T17:36:53+08:00 INFO Waiting for automatic snapd restart... code 2901c5ac from Visual Studio Code (vscode✓) installed px4_user@DESKTOP-807L394:~/PX4-Autopilot$ code . mkdir: cannot create directory ‘’: No such file or directory To use Visual Studio Code with the Windows Subsystem for Linux, please install Visual Studio Code in Windows and uninstall the Linux version in WSL. You can then use the `code` command in a WSL terminal just as you would in a normal command prompt. Do you want to continue anyway? [y/N] y To no longer see this prompt, start Visual Studio Code with the environment variable DONT_PROMPT_WSL_INSTALL defined. px4_user@DESKTOP-807L394:~/PX4-Autopilot$ code . mkdir: cannot create directory ‘’: No such file or directory To use Visual Studio Code with the Windows Subsystem for Linux, please install Visual Studio Code in Windows and uninstall the Linux version in WSL. You can then use the `code` command in a WSL terminal just as you would in a normal command prompt. Do you want to continue anyway? [y/N] y To no longer see this prompt, start Visual Studio Code with the environment variable DONT_PROMPT_WSL_INSTALL defined. px4_user@DESKTOP-807L394:~/PX4-Autopilot$ code . mkdir: cannot create directory ‘’: No such file or directory To use Visual Studio Code with the Windows Subsystem for Linux, please install Visual Studio Code in Windows and uninstall the Linux version in WSL. You can then use the `code` command in a WSL terminal just as you would in a normal command prompt. Do you want to continue anyway? [y/N] y To no longer see this prompt, start Visual Studio Code with the environment variable DONT_PROMPT_WSL_INSTALL defined. 为什么打不开code
07-11
资源下载链接为: https://pan.quark.cn/s/67c535f75d4c 在机器人技术中,轨迹规划是实现机器人从一个位置平稳高效移动到另一个位置的核心环节。本资源提供了一套基于 MATLAB 的机器人轨迹规划程序,涵盖了关节空间和笛卡尔空间两种规划方式。MATLAB 是一种强大的数值计算与可视化工具,凭借其灵活易用的特点,常被用于机器人控制算法的开发与仿真。 关节空间轨迹规划主要关注机器人各关节角度的变化,生成从初始配置到目标配置的连续路径。其关键知识点包括: 关节变量:指机器人各关节的旋转角度或伸缩长度。 运动学逆解:通过数学方法从末端执行器的目标位置反推关节变量。 路径平滑:确保关节变量轨迹连续且无抖动,常用方法有 S 型曲线拟合、多项式插值等。 速度和加速度限制:考虑关节的实际物理限制,确保轨迹在允许的动态范围内。 碰撞避免:在规划过程中避免关节与其他物体发生碰撞。 笛卡尔空间轨迹规划直接处理机器人末端执行器在工作空间中的位置和姿态变化,涉及以下内容: 工作空间:机器人可到达的所有三维空间点的集合。 路径规划:在工作空间中找到一条从起点到终点的无碰撞路径。 障碍物表示:采用二维或三维网格、Voronoi 图、Octree 等数据结构表示工作空间中的障碍物。 轨迹生成:通过样条曲线、直线插值等方法生成平滑路径。 实时更新:在规划过程中实时检测并避开新出现的障碍物。 在 MATLAB 中实现上述规划方法,可以借助其内置函数和工具箱: 优化工具箱:用于解决运动学逆解和路径规划中的优化问题。 Simulink:可视化建模环境,适合构建和仿真复杂的控制系统。 ODE 求解器:如 ode45,用于求解机器人动力学方程和轨迹执行过程中的运动学问题。 在实际应用中,通常会结合关节空间和笛卡尔空间的规划方法。先在关节空间生成平滑轨迹,再通过运动学正解将关节轨迹转换为笛卡
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值