UVA-810 筛子难题 题解答案代码 算法竞赛入门经典第二版

2023-10-30

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

题目并不算难,但是有一些需要注意的事情。

1. 骰子样式是确定的,而且题目中的图示正确的。

2. 根据骰子的两个相邻的面(例如题目给出的正面和顶面),可以确定整个骰子在桌面的每个面的位置。但是这个位置确定以及骰子在转动时的转换关系有点难找到规律。我用的一种比较繁琐的(但容易理解的)方式确定转动后骰子的位置。

3. 题目中并未限制骰子经过重复的点,也就是说每个点可以走多次。一开始我以为不能重复走。样例中的第二个迷宫就碰到了重复走的(2,2)结点。

4. 虽然可以重复走,但是如果不加以限制,那么会造成死循环,一直找不到终点。我一开始加的条件是在位置重复时,进入的方向不能一致,然后报错。后面又试了骰子面的位置不能一致,即顶面和正面位置不能一致,就对了。如果设置方向不能一致+骰子面的位置不能一致,那么还会进入死循环。我的理解是,即使进入的时候方向不一致,只要进入后骰子面的位置一致了,那么它随后进入其他结点的判断条件是一致的,即应该不能重复进入,给与限制。

5. 题目中提到在存在路径的情况下是唯一解,因此我们只需要用深度优先遍历一次就可以了。这里注意,uDebug中的部分例子不止存在一个解。

6. 由于最后需要输出路径,因此我们需要记录经过的每一个位置和方向。我使用了一个二维数组记录了经过每个位置时的方向。最后根据终点回溯到起点即可。这里注意,由于位置可以重复进入,因此只记录方向是不够的,还必须记录顺序,即第一次经过,第二次经过要进行顺序的区分。

我使用的判断骰子位置的方法:

1. 首先按照顺序,把每一个骰子周围的结点都记录下来,按照“顺时针 上 右 下 左 背”的顺序。这样就总结出了骰子面之间的关系。

2. 另正面和顶面以及方向作为输入,计算新的顶面和正面。

在确定了正面的情况下,一个骰子的顶面可能是正面的四个邻边的每一个。而我们又整理了上面的关系。根据这些就可以判断。例如:

在骰子面关系中的顶面就是实际的顶面时,如果向右移动,此时顶面就是原来的左面。

在骰子面关系中的左面就是实际的顶面时,如果向右移动,此时顶面就是原来的下面。

这个判断需要根据每种邻边位置和每个转动分别判断,因此比较繁琐。但是如果画个图分析,这个关系还是非常清晰的。

#include<string>
#include<string.h>
#include<iostream>
#include<vector>
using namespace std;

struct PATH {
	int p;
	int top, face;
};

int graph[12][12];
vector<PATH> path[12][12]; 
int row, column;
int startr, startc;
bool flag, startFlag;
// 下 右 上 左
int Step[5][2] = {{}, {1, 0}, {0, 1}, {-1, 0}, {0, -1}};

int pathArr[110][2];
int pathLen;

// 顺时针 上 右 下 左 背 
int Die[7][5] = {
{},
{5, 3, 2, 4, 6},
{1, 3, 6, 4, 5},
{1, 5, 6, 2, 4},
{6, 5, 1 ,2, 3},
{3, 1, 4, 6, 2},
{3, 5, 4, 2, 1},
};

bool judgeStep(int r, int c) {
	if(r <= 0 || r > row) return false;
	if(c <= 0 || c > column) return false;
	return true;
}

void getDieStatus(int top, int face, int step, int *topn, int *facen) {
	// 顺着放的 
	if(Die[face][0] == top) {
		switch(step) {
			case 1:
				*facen = Die[face][0];
				*topn = Die[face][4];
				break;
			case 2:
				*facen = face;
				*topn = Die[face][3];
				break;
			case 3:
				*facen = Die[face][2];
				*topn = face;
				break;
			case 4:
				*facen = face;
				*topn = Die[face][1];
				break;
		}
		return;
	}
	if(Die[face][2] == top) {
		// 逆着放的
		switch(step) {
			case 1:
				*facen = Die[face][2];
				*topn = Die[face][4];
				break;
			case 2:
				*facen = face;
				*topn = Die[face][1];
				break;
			case 3:
				*facen = Die[face][0];
				*topn = face;
				break;
			case 4:
				*facen = face;
				*topn = Die[face][3];
				break;
		}
		return;
	}
	if(Die[face][3] == top) {
		// 左侧的当顶
		switch(step) {
			case 1:
				*facen = Die[face][3];
				*topn = Die[face][4];
				break;
			case 2:
				*facen = face;
				*topn = Die[face][2];
				break;
			case 3:
				*facen = Die[face][1];
				*topn = face;
				break;
			case 4:
				*facen = face;
				*topn = Die[face][0];
				break;
		}
		return;
	}
	if(Die[face][1] == top) {
		// 左侧的当顶
		switch(step) {
			case 1:
				*facen = Die[face][1];
				*topn = Die[face][4];
				break;
			case 2:
				*facen = face;
				*topn = Die[face][0];
				break;
			case 3:
				*facen = Die[face][3];
				*topn = face;
				break;
			case 4:
				*facen = face;
				*topn = Die[face][2];
				break;
		}
		return;
	}
}

bool judgePath(int r, int c, int step, int top, int face) {
	for(int i = 0; i < path[r][c].size(); ++i) {
		if(path[r][c][i].top == top && path[r][c][i].face == face) return false;
	}
	return true;
}

void work(int r, int c, int top, int face) {
	if(startFlag && r == startr && c == startc) {
		flag = true;
		return;
	}
	startFlag = true;
	// cout << r << " " << c << endl;
	int i, j, rn, cn, topn, facen; 
	for(i = 1; i < 5; ++i) {
		rn = r + Step[i][0];
		cn = c + Step[i][1];
		if(!judgeStep(rn, cn)) continue;
		if(flag) return;
		if(graph[rn][cn] != -1 && graph[rn][cn] != top) continue;
		getDieStatus(top, face, i, &topn, &facen);
		if(!judgePath(rn, cn, i, topn, facen)) continue;
		path[rn][cn].push_back({i, topn, facen});
		work(rn, cn, topn, facen);
		if(flag) return;
		path[rn][cn].pop_back();
	}
}

void getPathArr() {
	int r, c, rn, cn;
	int i, j, k, step;
	pathLen = 0;
	r = startr, c = startc;
	do {
		pathArr[pathLen][0] = r;
		pathArr[pathLen][1] = c;
		++pathLen;
		step = path[r][c][path[r][c].size() - 1].p;
		rn = r-Step[step][0];
		cn = c-Step[step][1];
		// cout << path[r][c].size() - 1 << "  " << rn << " " << cn << endl;
		path[r][c].pop_back();
		r = rn;
		c = cn;
	} while(r != startr || c != startc);
	pathArr[pathLen][0] = r;
	pathArr[pathLen][1] = c;
	++pathLen;
}

int main() {
	string line;
	int top, face;
	int i, j, k;
	while(cin >> line && line != "END") {
		cout << line << endl;
		cin >> row >> column >> startr >> startc >> top >> face;
		for(i = 1; i <= row; ++i) {
			for(j = 1; j <= column; ++j) {
				 cin >> graph[i][j];
				 path[i][j] = vector<PATH>();
			}
		}
		flag = false; startFlag = false;
		work(startr, startc, top, face);
		if(!flag) {
			cout << "  No Solution Possible" << endl;
			continue;
		}
		getPathArr();
		cout << "  ";
		for(i = 1; i <= pathLen; ++i) {
			cout << "(" << pathArr[pathLen-i][0] << "," << pathArr[pathLen-i][1] << ")";
			if(i != pathLen) cout << ",";
			if(i % 9 == 0 && i != pathLen) cout << endl << "  ";
		}
		cout << endl;
	}
	return 0;
} 

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

UVA-810 筛子难题 题解答案代码 算法竞赛入门经典第二版 的相关文章

  • 【计算机视觉

    文章目录 一 检测相关 6篇 1 1 ALWOD Active Learning for Weakly Supervised Object Detection 1 2 mEBAL2 Database and Benchmark Image

随机推荐

  • C语言六种方法求素数(质数) 最全 输出2-100以内的所有素数 求1000以内的所有素数

    方法一 挨个遍历 从1 1000都试一次 通俗易懂的方法 include
  • 优秀程序员

    优秀程序员 拷贝型 新手型 学习型 实现型 架构型 1 拷贝型 拷贝型选手就是传说中的 代码拷贝员 了 他们对实现功能几乎没有思路 所作的事情就是从网上或是之前其他团队成员写的代码中拷贝出片段 然后放到项目中 如果运行项目出现了期望结果 则
  • 闲鱼无货源新玩法,从入门到精通,由浅入深教你怎么去做

    标题 闲鱼无货源新玩法 从入门到精通 由浅入深教你如何经营成功 随着电商的兴起 许多人开始利用平台经营自己的小生意 在这篇文章中 我们将聚焦于闲鱼平台 并分享关于如何从入门到精通运营成功的闲鱼无货源新玩法 以下是一些关键词 将帮助您更好地了
  • 7-1 二叉树的基本运算 (10 分)

    本习题为二叉树的基本运算练习 要求依次实现如下功能 1 输入一个使用 括号表示法 表示的二叉树 每个节点的数据为一个字符 请使用二叉链的存储方式构建二叉树B 2 使用中序遍历法遍历构建的二叉树 输出中序遍历的序列 3 输出该二叉树的高度 深
  • 【simulink】Three-PhaseV-I Measurement(三相电压电流测量)

    三相电压测量模块 MATLAB 三相电压电流测量模块怎么用 simulink Three PhaseV I Measurement 三相电压电流测量
  • 10X Genomics单细胞转录组测序

    一 单细胞及普通转录组比较 单细胞转录组测序 scRNA seq 在单个细胞水平上构建每个细胞的基因表达谱 反映细胞异质性 发现新的细胞类型 了解细胞表达调控机制 通过选取不同时间点的样本 再进行单细胞转录组测序 能够在单细胞水平获得基因
  • Java类加载

    类加载 执行 类加载 过程 对象的创建 类加载器 双亲委派 打破双亲委派 常见以tomcat和SPI为例 tomcat SPI 执行 解释执行 or 编译执行 关于编译 JIT编译器与解释器的工作模式 JIT编译器 分层编译 热点监测 热点
  • uniapp项目中给相机相册图片添加水印功能。

    效果如图 废话不多说 直接上代码吧 哦多说一句 在使用下面组件时需要在uniapp项目中安装uView组件库uView官网 详细的安装流程可以看这篇文章uView安装教程 也可以去官网查看官方文档 上面介绍的很清楚 添加水印组件hpy wa
  • 控制科学与工程 计算机那个好,控制科学与工程(自动化)最好的94所大学排名

    控制科学与工程是工科的四大 王牌 学科之一 是除了电气工程 机械制造 土木工程 计算机科学与技术外 比较 热门 的工科专业之一 同电气工程相比 控制科学与工程更加偏向控制 自动化 现场总线以及系统集成等方向 实际上 控制科学与工程很多人可能
  • redux和react-redux结合书写计数器

    安装包 npm install redux npm install react redux npm install redux thunk 如果使用了异步action的话 需要安装 npm install antd ant design U
  • 三极管流水灯电路设计

    随着科学技术的发展 电力电子设备与人们的工作 生活的关系日益密切 各种小套件层出不穷 功能多样 本文所设计的电子制作可以说是电子初学者学习电子的最佳入门制作 其制作方式容易 趣味横生 更能提高初学者的动手能力 让初学者在制作学习中感受电子
  • java 实现a系统到b系统的跳转_A-B系统快捷的登陆的验证设计

    用户X在A系统浏览器端请求接口1要求登陆到系统B A系统检测到用户X还没有登陆到B系统的认证密钥R 于是A系统产生 TOKEN 1 让用户X的浏览器跳转页面到B系统登陆绑定接口 B系统在后台使用该TOKEN 1 直接跟 系统A 进行确认验证
  • 记录一下2023.2kali的默认密码和修改root用户密码的方法

    要水一篇博客了 默认登录用户名 密码 kali kali 切换root用户 sudo su 这时输入的密码是kali 然后就切换到了root用户 输入passwd root 提示修改新密码 根据提示输入两遍新密码就修改了root用户的密码啦
  • 网络编程之本地套接字和网络套接字比较与本地套接字通信案例01

    1 socket IPC 本地套接字domain 1 1 本地通信的方法 1 pipe mkfifo 两者实现最简单 2 mmap 非血缘关系进程间 3 信号 开销小 4 domain 稳定性最好 注意 在本节domain称之为本地套接字
  • Jstat -gc 参数说明

    Jstat gc 参数说明 Jstat gc 参数说明 Jstat gc 参数说明 S0C 第一个幸存区的大小 S1C 第二个幸存区的大小 S0U 第一个幸存区的使用大小 S1U 第二个幸存区的使用大小 EC 伊甸园区的大小 EU 伊甸园区
  • list里面装tensor(pytorch的)如何合并起来

    问题简述 使用pytorch中tensor时 有时需要将多个tensor合并成一个高维tensor 或者是list中装着多个同纬度的tensor 想让这个list转为tensor 核心方法 torch stack def stack ten
  • ‘settings.xml’ has syntax errors less… 和Parent ‘org.springframework.boot’has problems less…的问题解决

    目录 一 背景介绍 二 报错信息 三 原因分析与处理 1 注意maven与jar包版本匹配问题 2 缺少资源 参考博文 一 背景介绍 在自己笔记本虚拟机中导入一个已经写好的Maven工程 经过前文中介绍的离线加载maven处理方法 解决的大
  • 操作系统用户态和核心态和CPU上下文切换

    目录 操作系统用户态和核心态 用户态和核心态 操作系统用户态和核心态是如何交换的 系统调用 CPU上下文 什么是CPU上下文和CPU上下文切换 CPU为什么要进行上下文切换 操作系统用户态和核心态 用户态和核心态 操作系统两种状态 用户态和
  • [SWPU CTF]之Misc篇(NSSCTF)刷题记录⑥

    NSSCTF Misc篇 SWPUCTF 长城杯 2021 院校组 签到 巅峰极客 2021 签到 羊城杯 2021 签到题 鹤城杯 2021 流量分析 SWPU 2019 神奇的二维码 NISACTF 2022 为什么我什么都看不见 NI
  • UVA-810 筛子难题 题解答案代码 算法竞赛入门经典第二版

    GitHub jzplp aoapc UVA Answer 算法竞赛入门经典 例题和习题答案 刘汝佳 第二版 题目并不算难 但是有一些需要注意的事情 1 骰子样式是确定的 而且题目中的图示正确的 2 根据骰子的两个相邻的面 例如题目给出的正