UVA-1343 旋转游戏 题解答案代码 算法竞赛入门经典第二版
GitHub - jzplp/aoapc-UVA-Answer: 算法竞赛入门经典 例题和习题答案 刘汝佳 第二版
题目其实不难,但是耗费了我较多时间。
这种题关键就是在于找到约束条件,我在DFS的基础上,试了很多种策略:
1. 对3种数字,每种数字递归遍历一次,这样每次只需要关注一种数字的变化,情况更少。
2. 使用一个long long类型的数字作为map的key,key表示这种数字在图形中分别的位置,value表示在第几步访问过。如果重复访问且步数更长,则不继续递归。
3. 使用剪枝策略,认为不符合情况结点不继续遍历。(但是我想的剪枝方法不合理,使用了之后是错误的,在最后有给出)
4. 迭代加深搜索,一层一层更深的查找。适用于本题次数最少的要求。
5. 乐观估价函数:在中心每个点的值不对的情况下,每个点都至少需要一次移动才能正确。因此估价函数为 不正确的点数+现有的步数 <= 要求的最大步数。
上述的方法是结合使用的,一开始没想到估价函数,一直在剪枝策略中纠结,然后一直超时。最后换成了估价函数,时间瞬间缩短了。
虽然移动的可能性是无限的,但是最多的移动次数也就是十几次。
AC代码
#include<stdio.h>
#include<map> 
#include<string.h>#define MAXLEN 15using namespace std;int arr[24];
int arrCon[4][7];
// 是否访问过的记录
map<long long, int> mp;
// 记录三种数字完成时的移动情况 
char moves[3][MAXLEN + 5];
// 移动数组的长度 
int moveCount[3];
// 每个移动数组代表的移动类型(可能并不是下表所指示的那个) 
int moveType[3];// 从输入数据转换为四数组模式 
void convertArr() {int i;arrCon[0][0] = arr[0]; arrCon[1][0] = arr[1];arrCon[0][1] = arr[2]; arrCon[1][1] = arr[3];for(i = 0; i < 7; ++i) arrCon[2][i] = arr[4 + i];arrCon[0][2] = arr[6]; arrCon[1][2] = arr[8];arrCon[0][3] = arr[11]; arrCon[1][3] = arr[12];for(i = 0; i < 7; ++i) arrCon[3][i] = arr[13 + i];arrCon[0][4] = arr[15]; arrCon[1][4] = arr[17];arrCon[0][5] = arr[20]; arrCon[1][5] = arr[21];arrCon[0][6] = arr[22]; arrCon[1][6] = arr[23];
}// 对一个数组移动位置 type->0 往大移动 type->1 往小移动
void moveArr(int *arrSrc, int type) {int t, i;if(type == 0) {t = arrSrc[6];for(i = 6; i > 0; --i) arrSrc[i] = arrSrc[i-1];arrSrc[0] = t;} else {t = arrSrc[0];for(i = 0; i < 6; ++i) arrSrc[i] = arrSrc[i+1];arrSrc[6] = t;}
}// 按照某个方向移动  flag->1 移动 flag->0 恢复移动 
void moveStep(int num, bool flag) {bool type;switch(num) {case 0:case 5:type = num < 4 ? 1 : 0;type = flag ? type : !type;moveArr(arrCon[0], type);arrCon[2][2] = arrCon[0][2];arrCon[3][2] = arrCon[0][4];break;case 1:case 4:type = num < 4 ? 1 : 0;type = flag ? type : !type;moveArr(arrCon[1], type);arrCon[2][4] = arrCon[1][2];arrCon[3][4] = arrCon[1][4];break;case 2:case 7:type = num < 4 ? 0 : 1;type = flag ? type : !type;moveArr(arrCon[2], type);arrCon[0][2] = arrCon[2][2];arrCon[1][2] = arrCon[2][4];break;case 3:case 6:type = num < 4 ? 0 : 1;type = flag ? type : !type;moveArr(arrCon[3], type);arrCon[0][4] = arrCon[3][2];arrCon[1][4] = arrCon[3][4];break;}
}// 是否成功 返回成功的字符 否则0 
int isArrive() {int num = arrCon[0][2];if(arrCon[0][3] != num || arrCon[0][4] != num || arrCon[1][2] != num || arrCon[1][3] != num) return 0;if(arrCon[1][4] != num || arrCon[2][3] != num || arrCon[3][3] != num)return 0;return num;
}// 根据数字在四数组中的位置,转换为0-27的数字数组 
long long getArrPos(int num) {int i, j;long long sum = 0;for(i = 0; i < 4; ++i) {for(j = 0; j < 7; ++j) {if(arrCon[i][j] == num) {if(i < 2) {sum = (sum << 5) + i * 7 + j;} else {if(j == 2 || j == 4) continue;sum = (sum << 5) + i * 7 + j;}}}}return sum;
}// 剪枝
bool shouldMove(int num, int step) {switch(step) {case 0:if(arrCon[0][5] == num || arrCon[0][6] == num || arrCon[0][4] == num) return true;break;case 1:if(arrCon[1][5] == num || arrCon[1][6] == num || arrCon[1][4] == num) return true;break;case 2:if(arrCon[2][0] == num || arrCon[2][1] == num || arrCon[2][2] == num) return true;break;case 3:if(arrCon[3][0] == num || arrCon[3][1] == num || arrCon[3][2] == num) return true;break;case 4:if(arrCon[1][0] == num || arrCon[1][1] == num || arrCon[1][2] == num) return true;break;case 5:if(arrCon[0][0] == num || arrCon[0][1] == num || arrCon[0][2] == num) return true;break;case 6:if(arrCon[3][5] == num || arrCon[3][6] == num || arrCon[3][4] == num) return true;break;case 7:if(arrCon[2][5] == num || arrCon[2][6] == num || arrCon[2][4] == num) return true;break;}return false;
}// 估价函数 true代表有机会 false代表没机会 
bool hvalue(int num, int stepCount, int k) {int i, j, value = 0;for(i = 0; i < 4; ++i) {if(arrCon[i][3] != num) value += 1;}if(arrCon[0][2] != num) value += 1;if(arrCon[0][4] != num) value += 1;if(arrCon[1][2] != num) value += 1;if(arrCon[1][4] != num) value += 1;return stepCount + value < k;
}//递归寻找 
int getValue(int num, int stepCount, int k) {int resArr = isArrive();if(resArr) {moveType[num - 1] = resArr;return stepCount;}if(stepCount >= k) return 0;if(!hvalue(num, stepCount, k))	return 0;int i, count, res;long long sum; // printf(" ------ %d\n", stepCount);for(i = 0; i < 8; ++i) {// if(!shouldMove(num, i)) continue;// 移动moveStep(i, true);// printf(" ----------- %d\n", isFind(num));sum = getArrPos(num);count = mp[sum];if(!count || count > stepCount) {mp[sum] = stepCount;// 记录步骤 moves[num-1][stepCount] = i;// 访问子节点res = getValue(num, stepCount+1, k);if(res) {// 复位moveStep(i, false); return res;}}// 复位moveStep(i, false);}return 0;
}int getRes(int k) {int i, j, mini, minV;for(i = 0; i < 3; ++i) {mp.clear();long long sum = getArrPos(i+1);mp[sum] = 0;moveCount[i] = getValue(i+1, 0, k);if(moveCount[i] > 0) k = moveCount[i];// printf("-- %d %d %d \n", k, i, moveCount[i-1]);// moves[i-1][moveCount[i-1]] = 0;}minV = MAXLEN + 10;mini = -1;for(i = 0; i < 3; ++i) {if(moveCount[i] == 0) continue;// printf( "[]%d\n", moveCount[i]);if(minV > moveCount[i]) {minV = moveCount[i];mini = i;} else if(minV == moveCount[i]) {if(strcmp(moves[mini], moves[i]) > 0) {minV = moveCount[i];mini = i;}}}return mini;
}int main() {int i, j, k;while(1) {if(scanf("%d", &arr[0]) != 1 || arr[0] == 0) break;for(i = 1; i < 24; ++i) {scanf("%d", &arr[i]);}convertArr();int resType = isArrive();if(resType) {printf("No moves needed\n");printf("%d\n", resType);continue;}for(i = 1; i < MAXLEN; ++i) {k = getRes(i);if(k >= 0) break;}if(moveCount[k] == 0) {printf("No moves needed\n");} else {for(i = 0; i < moveCount[k]; ++i) {printf("%c", moves[k][i] + 'A');}putchar('\n'); }printf("%d\n", moveType[k]);}return 0;
}
错误的剪枝策略:(不要使用))
// 错误的剪枝策略,
bool shouldMove(int num, int step) {switch(step) {case 0:if(arrCon[0][5] == num || arrCon[0][6] == num || arrCon[0][4] == num) return true;break;case 1:if(arrCon[1][5] == num || arrCon[1][6] == num || arrCon[1][4] == num) return true;break;case 2:if(arrCon[2][0] == num || arrCon[2][1] == num || arrCon[2][2] == num) return true;break;case 3:if(arrCon[3][0] == num || arrCon[3][1] == num || arrCon[3][2] == num) return true;break;case 4:if(arrCon[1][0] == num || arrCon[1][1] == num || arrCon[1][2] == num) return true;break;case 5:if(arrCon[0][0] == num || arrCon[0][1] == num || arrCon[0][2] == num) return true;break;case 6:if(arrCon[3][5] == num || arrCon[3][6] == num || arrCon[3][4] == num) return true;break;case 7:if(arrCon[2][5] == num || arrCon[2][6] == num || arrCon[2][4] == num) return true;break;}return false;
}相关文章:
UVA-1343 旋转游戏 题解答案代码 算法竞赛入门经典第二版
GitHub - jzplp/aoapc-UVA-Answer: 算法竞赛入门经典 例题和习题答案 刘汝佳 第二版 题目其实不难,但是耗费了我较多时间。 这种题关键就是在于找到约束条件,我在DFS的基础上,试了很多种策略: 1. 对3种数字,每种数字…...
 
【运维篇】二、配置文件与多环境控制
文章目录 1、临时属性2、IDEA中的临时属性3、配置文件4级分类4、关于四级分类的思考5、自定义配置文件6、多环境开发(yaml版)7、配置文件按环境分类8、include与group再细粒度9、一点思考10、多环境开发兼容问题 1、临时属性 jar包或者镜像已经打完了&a…...
【WFA】 VHT-5.2.27 Pre-requisite throughput lower than expected
先看仪表log,可以看到log中只有0.00346666666667Mbps,说明了速率很低 ~~~~~ Storing throughput ~~~~~ Mon, 11 Sep 2023 13:13:06 INFO strmTimeStampList2 count 1 Mon, 11 Sep 2023 13:13:06 INFO Storing $X1 = 0.00346666666667 [Mbps] Mon, 11 Sep 2023 13:13:…...
 
Pytorch史上最全torch全版本离线文件下载地址大全(9月最新)
以下为pytorch官网的全版本torch文件离线下载地址 torch全版本whl文件离线下载大全https://download.pytorch.org/whl/torch/其中的文件版本信息如下所示(部分版本信息,根据需要仔细寻找进行下载):...
CentOS服务器利用docker搭建中间件命令集合
一、挂载服务器磁盘 #挂盘语句 fdisk /dev/vdb 在分别输入n、p、1、2048、1048575999、w mkfs.ext4 /dev/vdb mkdir /data echo /dev/vdb /data ext4 defaults 0 0 >> /etc/fstab mount -a df -hfirewall-cmd --zonepublic --add-port8002/tcp --permanent firewall-c…...
 
Flask狼书笔记 | 09_图片社交网站 - 长文
文章目录 9 图片社交网站9.1 项目组织架构9.2 编写程序骨架9.3 高级用户认证9.4 基于用户角色的权限管理9.5 使用Flask-Dropzone优化文件上传9.6 使用Flask-Avatars处理用户头像9.7 图片展示与管理9.8 收藏图片9.9 用户关注9.10 消息提醒9.11用户资料与账户设置9.12 首页与探索…...
 
【链表】K 个一组翻转链表-力扣 25 题
💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kuan 的首页,持续学…...
 
jdk17新特性
JDK17新特性 jdk17下载地址:https://download.oracle.com/java/17/latest/jdk-17_windows-x64_bin.exe JDK 17 文档 - 首页 (oracle.com) 垃圾回收器(Z Garbage Collector) 概述 JDK17引入名为ZGC(Z Garbage Collector&#x…...
 
爬虫项目(四):抓取网页所有图片
文章目录 一、书籍推荐二、完整代码三、运行结果 一、书籍推荐 推荐本人书籍《Python网络爬虫入门到实战》 ,详细介绍见👉: 《Python网络爬虫入门到实战》 书籍介绍 二、完整代码 原理:抓取该链接中所有的图片格式。基于seleni…...
 
短剧推广和小说推文在哪里授权介绍
短剧推广和小说推文都属于很热门的赛道,都可以通过“巨量推文”进行授权 在巨量推文找到想推广的小说或者短剧后申请推广即可,小说需要有回填作品信息,短剧为全自动,出数据后实时同步到平台...
Java:本地文件通过表单参数接口发送后大小变成0
问题 发现一个文件生成以后,如果不通过接口发送,大小就正常,通过接口发送,文件大小就变成0了,发送的文件也是0 空文件 代码 MultiValueMap<String, Object> form new LinkedMultiValueMap<>();FileSyst…...
 
Linux 共享内存
#include <sys/ipc.h> #include <sys/shm.h> int shmget(key_t key, size_t size, int shmflg);功能:创建一个新的内存段或者获得一个既有的共享内存段的标识。新创建的内存段中的数据都会被初始化为0参数:-key:key_t类型是一个整…...
druid在springboot中如何整合配置!
在Spring Boot中配置Druid作为数据源非常简单。Druid是一个高性能的数据库连接池,它提供了丰富的监控和统计功能,适用于各种数据库。以下是在Spring Boot中配置Druid数据源的步骤: 1. 添加Druid依赖: 首先,您需要在项…...
数据结构:栈
文章目录 栈一,概述二,添加数据三,删除数据 栈 一,概述 栈(Stack)是一种特殊的线性表,它只允许在一端进行插入和删除操作,通常被称为“后进先出”(Last In First Out&a…...
 
每日刷题-6
目录 一、选择题 二、算法题 1.Fibonacci数列 2.合法括号序列判断 一、选择题 1、 解析:内联函数是一种可以提高函数执行效率的方法,它的原理是编译时在函数调用点直接展开函数体的代码,从而避免了函数调用的开销。 但是,内联函…...
 
systrace使用注意事项
打开systrace文件报错:Unable to select a master clock domain because no path can be found from “SYSTRACE” to “LINUX_FTRACE_GLOBAL”. 使用systrace生成的trace.html文件无法打开,或者报上面的错误,可以选择下面这个方式࿱…...
RockyLinux9.2 网卡配置和nmcli、nmtui命令的使用
NetworkManager NetworkManager 是一个标准的Linux网络配置工具套件,支持服务器,也支持桌面环境, 发展到如今,绝大多数流行的发行版都支持它。 这套网络配置工具适用于 Rocky Linux 8 及更高版本。 nmcli是nm的命令行工具、nmt…...
Java线程池ThreadPoolExecutor应用(Spring Boot微服务)
记录:475 场景:在Spring Boot微服务中使用Java线程池ThreadPoolExecutor。实现Runnable接口提交线程任务到线程池。 版本:JDK 1.8,Spring Boot 2.6.3。 1.使用注解配置线程池ThreadPoolExecutor (1)说明 ThreadPoolExecutor,…...
QT5|C++|通过信号槽机制实现进度条更新
背景:最近在写一个删除90天数据显示进度的功能,实现思路是:通过信号槽捕获当前进度值实现。 备注:点击start按钮,开始更新进度条,直到100(每隔1s进行更新)举个栗子: 1、…...
 
什么是智能推荐?智能推荐的原理是什么?
一、智能推荐的魔力 2020年的愚人节晚间,罗永浩在抖音带货,相信你也被刷屏了吧。3小时的直播过程中,22款产品轮番出场,最终首播支付交易总额突破1.1亿、整场直播观看总人数超过4800万、总销售件数逾91万,粉丝打赏音浪…...
 
19c补丁后oracle属主变化,导致不能识别磁盘组
补丁后服务器重启,数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后,存在与用户组权限相关的问题。具体表现为,Oracle 实例的运行用户(oracle)和集…...
 
大数据学习栈记——Neo4j的安装与使用
本文介绍图数据库Neofj的安装与使用,操作系统:Ubuntu24.04,Neofj版本:2025.04.0。 Apt安装 Neofj可以进行官网安装:Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...
 
label-studio的使用教程(导入本地路径)
文章目录 1. 准备环境2. 脚本启动2.1 Windows2.2 Linux 3. 安装label-studio机器学习后端3.1 pip安装(推荐)3.2 GitHub仓库安装 4. 后端配置4.1 yolo环境4.2 引入后端模型4.3 修改脚本4.4 启动后端 5. 标注工程5.1 创建工程5.2 配置图片路径5.3 配置工程类型标签5.4 配置模型5.…...
Java 语言特性(面试系列1)
一、面向对象编程 1. 封装(Encapsulation) 定义:将数据(属性)和操作数据的方法绑定在一起,通过访问控制符(private、protected、public)隐藏内部实现细节。示例: public …...
 
微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】
微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来,Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...
 
Unity3D中Gfx.WaitForPresent优化方案
前言 在Unity中,Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染(即CPU被阻塞),这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案: 对惹,这里有一个游戏开发交流小组&…...
线程与协程
1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指:像函数调用/返回一样轻量地完成任务切换。 举例说明: 当你在程序中写一个函数调用: funcA() 然后 funcA 执行完后返回&…...
 
YSYX学习记录(八)
C语言,练习0: 先创建一个文件夹,我用的是物理机: 安装build-essential 练习1: 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件,随机修改或删除一部分,之后…...
【解密LSTM、GRU如何解决传统RNN梯度消失问题】
解密LSTM与GRU:如何让RNN变得更聪明? 在深度学习的世界里,循环神经网络(RNN)以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而,传统RNN存在的一个严重问题——梯度消失&#…...
 
MySQL 8.0 OCP 英文题库解析(十三)
Oracle 为庆祝 MySQL 30 周年,截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始,将英文题库免费公布出来,并进行解析,帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...
