UVA-1601 万圣节后的早晨 题解答案代码 算法竞赛入门经典第二版

news2025/1/12 1:46:22

GitHub - jzplp/aoapc-UVA-Answer: 算法竞赛入门经典 例题和习题答案 刘汝佳 第二版

以三个点的当前位置作为状态,广度优先遍历,找到终点即为最短次数。

注意:

一次可以移动多个点,但是每个点只能移动一步。在同一次中,B可以移动到A离开前的位置上,即如果A走了,B可以去A之前的位置。因此,这三个点的移动和判断是有先后顺序的。对每个状态遍历时,情况实际上有 3的全排列(值为6),以及每个点移动的可能四种位置: 3! * 4^3。当然因为墙的存在,因此并没有这么多。

由于最高只有3,因此我的全排列写的不怎么优雅,直接嵌套循环完成了。注意每个点可以动,也可以不动,因此我们要考虑只有一个点动,两个点动的情况。写全排列时。如果第一个点动了大现已经遍历过,这时候不能放入队列(因为在其他点不动的情况下,这个状态已经遍历过了)。但是如果后面的点还继续动,那么这并不是一个完整的状态,因此不应该终止全排列。

按照上面的方法做的话,耗时很久,我扣了点细节,最后终于压线AC。(时间限制12000ms)

1. 根据题目描述,很多节点周围都是墙,因此用邻接表效率更高一些。

2. 一个点的坐标位置为1-16, x和y很容易放到一个数字中存储的。相对于每次计算x1 == x2 && y1 == y2, 一个数字的计算次数更少。其实三个结点的xy位置应该可以整合为一个数字的,这样效率会更高。 

3. 我的答案中用到了struct,一些辅助的判断函数,使用引用而不是直接将整个对象值作为参数,性能会提高一些。

#include <stdio.h>
#include <string.h>
#include <queue>
#include <vector>

using namespace std;

int graph[20][20];
vector<int> graphVec[300];
int w, h, n;

struct Point {
  char ch;
  int pos;
};
Point initPoints[3];
Point suppPoints[3];

struct Status {
  int pos[3];
  int step;
};
Status origin, terminal;

bool access[300][300][300];

int steps[4][2] = { {1, 0}, {-1, 0}, {0, 1}, {0, -1} };

bool sameLetter(char small, char big) {
  return small == big - 'A' + 'a';
}
bool statusEqual(Status &s1, Status &s2) {
  for (int i = 0; i < n; ++i) {
    if (s1.pos[i] != s2.pos[i]) return false;
  }
  return true;
}

int xy2Num(int x, int y) {
  return x * 17 + y;
}

void num2XY(int num, int *x, int *y) {
  *x = num / 17;
  *y = num % 17;
}

bool judgeAcc(Status &s) {
  if (n == 1) return access[s.pos[0]][0][0];
  if (n == 2) return access[s.pos[0]][s.pos[1]][0];
  if (n == 3) return access[s.pos[0]][s.pos[1]][s.pos[2]];
}

void setAcc(Status &s) {
  if (n == 1) access[s.pos[0]][0][0] = true;
  if (n == 2) access[s.pos[0]][s.pos[1]][0] = true;
  if (n == 3) access[s.pos[0]][s.pos[1]][s.pos[2]] = true;
}

void printStatus(Status &s) {
  int x, y;
  for (int i = 0; i < n; ++i) {
    num2XY(s.pos[i], &x, &y);
    printf("[%d %d] ", x, y);
  }
  printf(" %d\n", s.step);
}

void printGraphVec() {
  int i, j, x, y;
  for(i = 0; i < 300; ++i) {
    if(graphVec[i].size()) {
      num2XY(i, &x, &y);
      printf("%d %d - ", x, y);
      for(j = 0; j < graphVec[i].size(); ++j) {
        num2XY(graphVec[i][j], &x, &y);
        printf("[%d %d] ", x, y);
      }
      putchar('\n');
    }
  }
  putchar('\n');
}

void init() {
  int i, j, k, initLen = 0, suppLen = 0;
  int x, y;
  memset(access, 0, sizeof(access));
  for(i = 0; i < 300; ++i) {
    graphVec[i].clear();
  }
  for (i = 1; i <= h; ++i) {
    while (getchar() != '\n') ;
    for (j = 1; j <= w; ++j)  {
      graph[i][j] = getchar();
      if (graph[i][j] >= 'a' && graph[i][j] <= 'z')
        initPoints[initLen++] = {char(graph[i][j]), xy2Num(i, j)};
      if (graph[i][j] >= 'A' && graph[i][j] <= 'Z')
        suppPoints[suppLen++] = {char(graph[i][j]), xy2Num(i, j)};
    }
  }

  for(i = 2; i < h; ++i) {
    for (j = 2; j < w; ++j)  {
      if(graph[i][j] == '#') continue;
      for(k = 0; k < 4; ++k) {
        x = i + steps[k][0];
        y = j + steps[k][1];
        if(graph[x][y] == '#') continue;
        graphVec[xy2Num(i, j)].push_back(xy2Num(x, y));
      }
    }
  }

  // printGraphVec();

  for (i = 0; i < n; ++i) {
    origin.pos[i] = initPoints[i].pos;
    for (j = 0; j < n; ++j) {
      if (sameLetter(initPoints[i].ch, suppPoints[j].ch)) {
        terminal.pos[i] = suppPoints[j].pos;
        break;
      }
    }
  }
  origin.step = 0;
  terminal.step = 0;
  setAcc(origin);
  // printStatus(origin);
  // printStatus(terminal);
}

bool judgePos(Status &s) {
  int i, j;
  for (i = 0; i < n; ++i) {
    for (j = 0; j < n; ++j) {
      if (i == j) continue;
      if (s.pos[i] == s.pos[j]) return false;
    }
  }
  return true;
}

int compute() {
  int i, j, k, a1, a2, a3;
  int num1, num2, num3, len1, len2, len3;
  queue<Status> qu;
  Status s0, s1, s2, s3;
  qu.push(origin);
  while (!qu.empty()) {
    s0 = qu.front();
    qu.pop();
    // putchar('\n');
    // printStatus(s0);
    s0.step++;
    for (i = 0; i < n; ++i) {
      num1 = s0.pos[i]; len1 = graphVec[num1].size();
      for (a1 = 0; a1 < len1; ++a1) {
        s1 = s0;
        s1.pos[i] = graphVec[num1][a1];
        if (!judgePos(s1)) continue;
        if (!judgeAcc(s1)) {
          // printStatus(s1);
          setAcc(s1); qu.push(s1);
		    }
        if (statusEqual(s1, terminal)) return s1.step;
        for (j = 0; j < n; ++j) {
          if (i == j) continue;
          num2 = s1.pos[j]; len2 = graphVec[num2].size();
          for (a2 = 0; a2 < len2; ++a2) {
            s2 = s1;
            s2.pos[j] = graphVec[num2][a2];
            if (!judgePos(s2)) continue;
            if (!judgeAcc(s2)) {
              // printStatus(s2);
              setAcc(s2); qu.push(s2);
            }
            if (statusEqual(s2, terminal)) return s2.step;
            for (k = 0; k < n; ++k) {
              if (k == i || k == j) continue;
              num3 = s2.pos[k]; len3 = graphVec[num3].size();
              for (a3 = 0; a3 < len3; ++a3) {
                s3 = s2;
                s3.pos[k] = graphVec[num3][a3];
                if (!judgePos(s3)) continue;
                if (!judgeAcc(s3)) {
                  // printStatus(s3);
                  setAcc(s3); qu.push(s3);
                }
                if (statusEqual(s3, terminal)) return s3.step;
              }
            }
          }
        }
        
      }
    }
  }
}

int main() {
  while (scanf("%d %d %d", &w, &h, &n) == 3 && w != 0) {
    init();
    printf("%d\n", compute());
  }
  return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/870562.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

人工智能监听——研究人员发现新的安全威胁

大学的一项新研究表明&#xff0c;人工智能 (AI) 可以通过按键声音识别密码&#xff0c;准确率超过 90%。 在通过 Zoom 等视频通话聊天时输入计算机密码可能会打开网络攻击的大门&#xff0c;一项新的研究表明&#xff0c;人工智能可以通过窃听打字声音来找出正在按下的按键。…

索引堆及其优化(Java 实例代码)

目录 索引堆及其优化 一、概念及其介绍 二、适用说明 三、结构图示 四、Java 实例代码 src/runoob/heap/IndexMaxHeap.java 文件代码&#xff1a; 索引堆及其优化 一、概念及其介绍 索引堆是对堆这个数据结构的优化。 索引堆使用了一个新的 int 类型的数组&#xff0c;…

JavaScript【BOM】

【BOM】 原创内容&#xff0c;转载请注明出处&#xff01; 一、BOM是什么 BOM&#xff08;Browser Object Model&#xff0c;浏览器对象模型&#xff09;是 JS 与 浏览器窗口交互的接口。 一些与浏览器改变尺寸、滚动条滚动相关的特效&#xff0c;都要借助 BOM 技术。 二、w…

Arduino+esp32学习笔记

学习目标&#xff1a; 使用Arduino配置好蓝牙或者wifi模块 学习使用python配置好蓝牙或者wifi模块 学习内容&#xff08;笔记&#xff09;&#xff1a; 一、 Arduino语法基础 Arduino语法是基于C的语法,C又是c基础上增加了面向对象思想等进阶语言。那就只记录没见过的。 单多…

【分布式】Viewstamped Replication Revisited

篇前感悟&#xff1a; 阅读分布式系统文章的意义其实并不在于你个人真正地去开发这样一个基于这种协议的系统&#xff0c;因为真正去开发一个高可用的分布式系统实在是太难了&#xff08;对我来说…&#xff09;更多的还是汲取其中的思想&#xff0c;包括设计思路&#xff0c;优…

高性能跨平台网络通信框架 HP-Socket v5.9.3

项目主页 : http://www.oschina.net/p/hp-socket开发文档 : https://www.docin.com/p-4478351216.html下载地址 : https://github.com/ldcsaa/HP-SocketQQ Group: 44636872, 663903943 v5.9.3 更新 一、主要更新 问题修复&#xff1a;通过 POST/PUT 等带有请求内容的 HTTP 方…

Vue主面板组件模板(简洁版)

文章目录 &#x1f412;个人主页&#x1f3c5;JavaEE系列专栏&#x1f4d6;前言&#xff1a;&#x1f380;源码如下&#xff1a; &#x1f412;个人主页 &#x1f3c5;JavaEE系列专栏 &#x1f4d6;前言&#xff1a; 本篇博客主要以介绍【&#x1f380;主面板组件模板&#xf…

怎么才能突破认知?别灌鸡汤行吗

怎么才能突破认知&#xff1f;别灌鸡汤行吗&#xff1f; 趣讲大白话&#xff1a;大部分人得一步一步来 【趣讲信息科技254期】 **************************** 孔子说有三种情况&#xff1a; 1生而知之&#xff1a;就是天生就会 2学而知之&#xff1a;需要后天学习 3困而学之&am…

【计算机网络】——数据链路层

二、组帧 1、字符计数法 帧头部使用一个字符来表示帧的大小(包括第一个计数字符) &#xff08;此处一字符一个字节&#xff09; 2、字符填充收尾定界法 特定字符来定界帧的首和尾。若帧中数据段出现等同于特定字符的字符内容&#xff0c;前置一个转义字符。(类似于正则表达…

读发布!设计与部署稳定的分布式系统(第2版)笔记30_为部署而设计

1. 部署行为是系统生命的重要组成部分 1.1. 只编写代码是不够的&#xff0c;只要没有在生产环境中运行&#xff0c;一切都不算完成 1.2. 要想取得成功&#xff0c;需要早早地频繁部署软件 1.3. 设计易于部署的软件非常有必要 1.4. 零停机部署就是目标 2. 机器与服务 2.1.…

HTML详解连载(4)

HTML详解连载&#xff08;4&#xff09; 专栏链接 [link](http://t.csdn.cn/xF0H3)下面进行专栏介绍 开始喽CSS定义书写位置示例注意 CSS引入方式内部样式表&#xff1a;学习使用 外部演示表&#xff1a;开发使用代码示例行内样式代码示例 选择器作用基础选择器标签选择器举例特…

Linux MQTT智能家居项目(LED界面的布局设置)

文章目录 前言一、LED界面布局准备工作二、LED界面布局三、逻辑实现总结 前言 上篇文章我们完成了主界面的布局设置那么这篇文章我们就来完成各个界面的布局设置吧。 一、LED界面布局准备工作 首先添加LED灯光控制的图标。 将选择好的LED图标添加进来&#xff1a; 图标可以…

gcc及其相关知识

目录 gcc工作流程 静态库的生成和使用&#xff08;该部分使用g进行代码的编译。 若使用gcc&#xff0c;也类似&#xff09; 动态库的制作和使用&#xff08;此处用gcc&#xff0c;g类似&#xff09; 动态库的命名规则 动态库的制作 动态库的使用 动态库和静态库的优缺点 静…

搭建Synopsis 数字IC IDE开发化境

安装平台信息&#xff1a; VMware15.5和centos7 至于为何要选择如上版本和为何不能直接在物理机上安装还不得而知&#xff0c;只是参考网上的文章是这样做的&#xff0c;先照搬过来&#xff0c;在安装操作中慢慢体会。 安装包内容如下&#xff1a; 使用默认配置&#xff0c;一…

CAN总线一些经典的现场故障

本文分析一些经典的CAN总线现场故障。 1、CAN总线的常见故障 CAN总线错误分析与解决 当CAN总线出现故障或数据传输异常时,往往会出现多种奇怪的故障现象,如仪表板显示异常,车辆无法启动,启动后无法熄灭,车辆动力性能下降,某些电控系统功能失等。 这是因为相关数据或信息…

第二十章 重要HL7操作场景 - 传入消息的双 ACK 序列

文章目录 第二十章 重要HL7操作场景 - 传入消息的双 ACK 序列传出消息的双 ACK 序列配置双 ACK 序列 第二十章 重要HL7操作场景 - 传入消息的双 ACK 序列 对于进入Production的消息&#xff0c;双重确认序列的工作原理如下图所示&#xff1a; 客户端应用程序将消息发送到Produ…

【数据结构•堆】轮廓线

题目描述 轮廓线   • 每一个建筑物用一个三元组表示(L, H, R), 表示左边界, 高度和右边界。   • 轮廓线用X, Y, X, Y…这样的交替式表示。   • 右图的轮廓线为: (1, 11, 3, 13, 9, 0, 12, 7, 16,3, 19, 18, 22, 3, 23, 13, 29, 0) 。   • 给N个建筑&#xff0c;求…

项目架构简介

目录 1 单体应用架构 2 垂直应用架构 3 分布式架构 3.1 RPC 3.2 SOA 4 微服务架构 本文介绍后台应用的各种架构,以及各架构的优缺点对比 1 单体应用架构 将所有的代码功能都写在一个项目中(例如:MVC结构,SSM框架),同时打包,同时部署 优点:便于管理,减少开发、维护、运维成…

GPT内功心法:搜索思维到GPT思维的转换

大家好,我是herosunly。985院校硕士毕业,现担任算法研究员一职,热衷于机器学习算法研究与应用。曾获得阿里云天池比赛第一名,CCF比赛第二名,科大讯飞比赛第三名。拥有多项发明专利。对机器学习和深度学习拥有自己独到的见解。曾经辅导过若干个非计算机专业的学生进入到算法…

2023国赛数学建模C题思路分析

文章目录 0 赛题思路1 竞赛信息2 竞赛时间3 建模常见问题类型3.1 分类问题3.2 优化问题3.3 预测问题3.4 评价问题 4 建模资料 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 1 竞赛信息 全国大学生数学建模…