UVA101

UVA101 The Blocks Problem

题目描述

PDF

输入格式

输出格式

输入输出样例 #1

输入 #1

复制代码
10
move 9 onto 1
move 8 over 1
move 7 over 1
move 6 over 1
pile 8 over 6
pile 8 over 5
move 2 over 1
move 4 over 9
quit

输出 #1

复制代码
0: 0
1: 1 9 2 4
2:
3: 3
4:
5: 5 8 7 6
6:
7:
8:
9:

题目大意

计算机科学很多领域会使用简单抽象模型做理论和实验研究。比如早期人工智能的规划与机器人研究(STRIPS)就使用积木世界模型,机械臂完成积木搬运任务。

本题要模拟简单积木世界,遵循给定规则。不用自己寻找达到目标状态的方案,而是编写程序让机械臂按照一系列指令操作积木。

初始状态:桌上有n块积木,编号0 ~ n-1,依次并排摆在桌面上,每块单独占一个位置。

机械臂操作积木的合法指令如下:

  • move a onto b
    其中 a、b 为积木编号,先将堆积在积木 a 和积木 b 上方的所有积木放回各自初始位置,再把积木 a 放到积木 b 之上。
  • move a over b
    其中 a、b 为积木编号,先将堆积在积木 a 上方的所有积木放回各自初始位置,再把积木 a 放到包含积木 b 的那一堆积木的顶端。
  • pile a onto b
    其中 a、b 为积木编号,将由积木 a 以及堆叠在 a 上方的所有积木组成的整叠积木移动到积木 b 之上。执行堆叠操作前,需要先把积木 b 上方的所有积木放回各自初始位置。堆叠在 a 上方的积木在移动时保持原有上下顺序不变。
  • pile a over b
    其中 a、b 为积木编号,将由积木 a 以及堆叠在 a 上方的所有积木组成的整叠积木,放到包含积木 b 的那一堆积木的顶端。堆叠在 a 上方的积木在移动时保持原有上下顺序不变。
  • quit
    终止积木世界的所有操作。

如果一条指令满足 a 等于 b,或者 a 与 b 原本就在同一堆积木中,则该指令为非法指令。所有非法指令都应当被忽略,不会对积木的摆放状态产生任何影响。

输入

第一行单独一个整数n,代表积木总数,0<n<25。之后每行一条指令,直到读到quit停止。保证所有指令语法正确。

输出

输出积木世界的最终状态。一共输出n行,对应原始位置0,1,...,n-1每行格式:位置号,冒号后面如果有积木,先加空格,接着输出这一堆积木编号,空格分隔,不能行尾多余空格;如果该位置没有积木,就只输出位置号。

解题思路

用一个二维列表保存每一堆积木,另外开一个数组记录每一块积木当前在哪一堆,用来快速查询位置,避免每次遍历查找。程序先读取积木总数,初始化状态,每块积木一开始单独占一堆。接着循环读取每一条指令,读到 quit 就停止输入。处理指令时先判断是否非法,a 等于 b 或者两块积木本来就在同一堆就直接跳过这条指令。如果指令里是 onto,就先把 b 上方所有积木放回各自初始位置;如果是 move 操作,就把 a 上方所有积木放回初始位置,再单独移动 a;如果是 pile 操作,就把 a 以及 a 上方的一整叠积木完整移过去,保持积木之间的上下顺序。移动积木时同步更新位置数组。全部指令处理完成后,按堆号从小到大输出每一堆里的积木。

完整代码

java 复制代码
import java.util.*;
public class TheBlocksProblem {
    private static List<List<Integer>> world;
    private static int[] positionOf;
    private static int n;
    private static List<String[]> readInput(Scanner scanner) {
        n = Integer.parseInt(scanner.nextLine().trim());
        initWorld(n);
        List<String[]> commands = new ArrayList<>();
        while (scanner.hasNextLine()) {
            String line = scanner.nextLine().trim();
            if (line.isEmpty()) continue;
            String[] tokens = line.split("\\s+");
            if (tokens[0].equals("quit")) {
                break;
            }
            commands.add(tokens);
        }
        return commands;
    }
    private static void initWorld(int n) {
        world = new ArrayList<>();
        positionOf = new int[n];
        for (int i = 0; i < n; i++) {
            List<Integer> pile = new ArrayList<>();
            pile.add(i);
            world.add(pile);
            positionOf[i] = i;
        }
    }
    private static void processCommands(List<String[]> commands) {
        for (String[] cmd : commands) {
            String action = cmd[0]; 
            int a = Integer.parseInt(cmd[1]);
            String prep = cmd[2];  
            int b = Integer.parseInt(cmd[3]);
            if (a == b || positionOf[a] == positionOf[b]) {
                continue;
            }
            if (prep.equals("onto")) {
                returnAbove(b);
            }
            if (action.equals("move")) {
                returnAbove(a);
                moveBlock(a, b);
            } else { // "pile"
                movePile(a, b);
            }
        }
    }
    private static void returnAbove(int block) {
        int pos = positionOf[block];
        List<Integer> pile = world.get(pos);
        int idx = pile.indexOf(block);
        for (int i = pile.size() - 1; i > idx; i--) {
            int topBlock = pile.remove(i);
            returnToInitial(topBlock);
        }
    }
    private static void returnToInitial(int block) {
        int initPos = block;
        positionOf[block] = initPos;
        world.get(initPos).add(block);
    }
    private static void moveBlock(int a, int b) {
        int posA = positionOf[a];
        int posB = positionOf[b];
        world.get(posA).remove(Integer.valueOf(a));
        world.get(posB).add(a);
        positionOf[a] = posB;
    }
    private static void movePile(int a, int b) {
        int posA = positionOf[a];
        int posB = positionOf[b];
        List<Integer> pileA = world.get(posA);
        int idx = pileA.indexOf(a);
        List<Integer> movingBlocks = new ArrayList<>(pileA.subList(idx, pileA.size()));
        pileA.subList(idx, pileA.size()).clear();
        for (int block : movingBlocks) {
            world.get(posB).add(block);
            positionOf[block] = posB;
        }
    }
    private static void printResult() {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < n; i++) {
            sb.append(i).append(":");
            List<Integer> pile = world.get(i);
            for (int block : pile) {
                sb.append(" ").append(block);
            }
            sb.append("\n");
        }
        System.out.print(sb);
    }
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        List<String[]> commands = readInput(sc);
        processCommands(commands);
        printResult();
        sc.close();
    }
}

测评结果

相关推荐
Lyyaoo.1 小时前
【回溯】【中等】全排列
java·数据结构·算法
xixingzhe21 小时前
spring boot对接Dify
java·spring boot·dify
数据狐(Datafox)1 小时前
京东商品详情API接口解析(附 JSON 样例)
java·开发语言·json
Wang's Blog1 小时前
Java框架快速入门: Spring Security+OAuth2之深度定制UserDetailsService与密码无缝升级
java·开发语言·spring
土司大王1 小时前
LeetCode 79 单词搜索:Java 回溯模板、网格 DFS 与剪枝优化
java·算法·leetcode·深度优先
白远山1 小时前
智慧场馆解决方案小程序系统开发实战与架构设计指南
java·开发语言·小程序·架构
霸道流氓气质1 小时前
Spring AI Alibaba vs LangChain4j:Java AI 框架选型深度指南
java·人工智能·spring
敲代码的嘎仔1 小时前
从零实现视频续播 + 学习进度统计:前端心跳、条件更新、GROUP BY 统计全链路拆解
java·前端·数据库·学习·面试·职场和发展·音视频
一个有温度的技术博主2 小时前
深入理解 Spring Boot 自动装配
java·spring boot·后端