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;
}

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

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

相关文章

VSCode『SSH』连接服务器『GUI界面』传输

前言 最近需要使用实验室的服务器训练带有 GUI 画面的 AI 算法模型&#xff08;pygame&#xff09;&#xff0c;但是我是使用 SSH 连接的&#xff0c;不能很好的显示模型训练的效果画面&#xff0c;所以下面将会讲解如何实现 SSH 连接传输 Linux GUI 画面的 注&#xff1a;我们…

Postman —— HTTP请求基础组成部分

一般来说&#xff0c;所有的HTTP Request都有最基础的4个部分组成&#xff1a;URL、 Method、 Headers和body。 &#xff08;1&#xff09;Method 要选择Request的Method是很简单的&#xff0c;Postman支持所有的请求方式。 &#xff08;2&#xff09;URL 要组装一条Request…

华为HCIA(五)

Vlan id 在802.1Q中 高级ACL不能匹配用户名和源MAC 2.4G频段被分为14个交叠的&#xff0c;错列的20MHz信道&#xff0c;信道编码从1到14&#xff0c;邻近的信道之间存在一定的重叠范围 STA通过Probe获取SSID信息 Snmp报文 网络管理设备异常发生时会发送trap报文 D类地址是…

基于Java网络书店商城设计实现(源码+lw+部署文档+讲解等)

博主介绍&#xff1a;✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专…

亚马逊云科技 Amazon Lightsail :一种在云服务器上运行容器的简单方法

当向开发人员介绍亚马逊云科技云服务时&#xff0c;通常会花一点时间来介绍并演示 Amazon Lightsail 。它是迄今为止开始使用亚马逊云科技的最简单方法。使用它&#xff0c;您在几分钟内即可在自己的虚拟服务器上运行您的应用程序。而后增加了在 Amazon Lightsail 上部署基于容…

C语言字符函数和字符串函数(1)

大家好&#xff0c;我们又见面了&#xff0c;让大家久等了&#xff0c;我们今天就来学习字符函数和字符串函数。 在开启今天的学习之前呢&#xff0c;我来解决一下一些小伙伴平时找不到库函数使用的烦恼&#xff0c;因为我们cplusplus.com最新版本不能够查询函数&#xff0c;我…

【面试题精讲】Mysql如何实现乐观锁

❝ 有的时候博客内容会有变动&#xff0c;首发博客是最新的&#xff0c;其他博客地址可能会未同步,认准https://blog.zysicyj.top ❞ 首发博客地址 文章更新计划 系列文章地址 在 MySQL 中&#xff0c;可以通过使用乐观锁来实现并发控制&#xff0c;以避免数据冲突和并发更新问…

排查disabled问题之谷歌新版本特性

问题复现 最近我突然接手一个后台的bug&#xff0c;这个后台很久没有迭代更新了&#xff0c;我也不熟悉业务&#xff0c;所以只能看一下源码&#xff0c;问题很快就复现&#xff0c;测试的修复操作也很正确&#xff0c;就是因为渲染的input标签中存在disableddisabled’属性导…

单片机论文参考:1、基于单片机的电子琴

摘要 随着社会的发展进步&#xff0c;音乐逐渐成为我们生活中很重要的一部分&#xff0c;有人曾说喜欢音乐的人不会向恶。我们都会抽空欣赏世界名曲&#xff0c;作为对精神的洗礼。本论文设计一个基于单片机的简易电子琴。电子琴是现代电子科技与音乐结合的产物&#xff0c;是一…

英国留学生务必谨慎使用ChatGPT!!!

ChatGPT&#xff08;全名&#xff1a;Chat Generative Pre-trained Transformer&#xff09;&#xff0c;是OpenAI研发的聊天机器人程序&#xff0c;于2022年11月30日发布。ChatGPT是人工智能技术驱动的自然语言处理工具&#xff0c;它能够基于在预训练阶段所见的模式和统计规律…

1.IAR-8051安装

新版安装教程&#xff1a;IAR EW for 8051 简介与安装 新版软件zhuce&#xff1a;IAR EW for 8051 软件注册 - 知乎 这个新版的我也放到网盘里面了&#xff0c;自己自行选择安装 一、下载IAR-8051 链接&#xff1a;https://pan.baidu.com/s/1mYwSQvSjAiSzltrEbK3yAw?pwd43cd …

【产品经理】深入B端SaaS产品设计核心理念

这几年各企业的B端业务都在做SaaS平台&#xff0c;但对SaaS的了解还不是完全全面&#xff0c;对于一些产品的定位以及设计还在探索中 本文讨论“为什么采用SaaS模式”、“SaaS产品有哪些”以及“如何做好SaaS产品设计”三个话题&#xff0c;核心是产品设计&#xff0c;主要从需…

9月19日学习记录

获取Windows系统的UUID cmd.exe中执行wmic csproduct get uuid QProcess p(0);p.start("cmd",QStringList()<<"/c"<<"wmic csproduct get uuid");p.waitForStarted();p.waitForFinished();QString strTempQString::fromLocal8Bit(p…

[python 刷题] 36 Valid Sudoku

[python 刷题] 36 Valid Sudoku 题目&#xff1a; Determine if a 9 x 9 Sudoku board is valid. Only the filled cells need to be validated according to the following rules: Each row must contain the digits 1-9 without repetition. Each column must contain the …

LabVIEW开发航天器模拟器的姿态控制和反作用轮动量管理

LabVIEW开发航天器模拟器的姿态控制和反作用轮动量管理 在过去十年中&#xff0c;航天器一直是现代技术进步的先决条件。迄今为止&#xff0c;为了更好地完成各种实际任务&#xff0c;已经在航天器姿态控制领域进行了大量研究。航天器一旦进入太空&#xff0c;就容易出现不确定…

CSS

CSS CSS是什么 层叠样式表 (Cascading Style Sheets).CSS 能够对网页中元素位置的排版进行像素级精确控制, 实现美化页面的效果. 能够做到页面的样式和结构分离.说白了就是让网页变得好看 什么是样式呢&#xff1f; 大小&#xff0c;位置&#xff0c;间距&#xff0c;颜色&a…

银行发展绿色金融,8条建议为您指路

在《财富潮涌&#xff1a;银行发展绿色经济创新路径》内容中&#xff0c;我们带大家了解了商业银行有关绿色财富、绿色服务及绿色运营的内容。今天&#xff0c;我们将阐述商业银行发展绿色金融的必要性以及在实践中商业银行应该如何发展色金融。 发展绿色金融的必要性与难点 1.…

国家开放大学考试难度如何

国家开放大学面相的学生群体主要是广大在职在岗员工和社会人士&#xff0c;所以国开的考试难度可以用“宽入宽出”四个字形容。 所谓的“宽入”指的是招生条件非常宽松&#xff0c;虽然有入学考试&#xff0c;但是所涉及的内容十分简单。 所谓的“宽出”指的是毕业条件非常简单…

可扩展性对物联网管理系统有哪些影响?

可扩展性对于物联网管理系统的设计和开发非常重要&#xff0c;它直接影响着系统的性能、可靠性和能耗等方面&#xff0c;是评估一个系统优劣的重要因素之一。可扩展性对物联网管理系统的影响主要体现在以下几个方面&#xff1a; 设备兼容性&#xff1a;物联网管理系统的可扩展性…

华为杯数学建模比赛经验分享

再过一周左右,第二十届华为杯数学建模比赛就要开赛了&#xff0c;所以今天分享一下个人数学建模比赛的经验。 今天给大家分享一期关于华为杯数学建模比赛的经验分享&#xff0c;我将从以下三个方面展开说明&#xff1a; &#xff08;1&#xff09;如何准备数学建模比赛&#x…