c语言15-puzzle解法,UVa 10181 15-Puzzle Problem 题解《挑战程序设计竞赛》

本文主要是介绍c语言15-puzzle解法,UVa 10181 15-Puzzle Problem 题解《挑战程序设计竞赛》,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

b514f673847d815eb3aef74213ecc9b1.png

f03d073da7c12e5229c56382e1a2d4f0.png

滑动拼图:给定拼图,求解决方案。

b514f673847d815eb3aef74213ecc9b1.png

951d1babec9cb4b5ac2a5aa7fcd25c4d.png

4.5开动脑筋智慧搜索

A*与IDA*

滑块拼图问题是否有解的判断方法是,先将表格平铺:

15c68f7f7c88d4ca2ddcc2da19b95304.png

然后计算N=逆序数对之和,e=空白所在的行数。若N+e为偶数,则有解,反之无解,证明在此。

然后估计最优解的下界,对所有非0数字,最理想的情况是表格中其他数字都不存在,不浪费一步避让,一路畅通无阻抵达目标。此时所需的步数为曼哈顿距离

be35128786aa502b4aad523ff2db51d6.png

5bff54ead5d28163dfcc09d9de6498e5.png

之后就是常规的IDA*搜索了。

#include 

#include 

#include 

#include 

using namespace std;

const int dy[4] = {0, 0, +1, -1};

const int dx[4] = {+1, -1, 0, 0};

const int direction[4] = {'R', 'L', 'D', 'U'};

const int MAX_N = 50;

string path;

int T[15][15], e_y, e_x;

// 最优解下界

int h()

{

int limit = 0;

for (int y = 0; y 

{

for (int x = 0; x 

{

if (T[y][x] == 0)

continue;

int goal_y = (T[y][x] - 1) / 4;

int goal_x = (T[y][x] - 1) % 4;

limit += abs(goal_y - y) + abs(goal_x - x); // 曼哈顿距离

}

}

return limit;

}

bool dfs(int current_steps, int prev_direction, int bound)

{

int limit = h();

if (limit == 0)

return true;

if (current_steps + limit > bound)

return false;

for (int i = 0; i 

{

if (i == (prev_direction ^ 1))  // 小三爷,不回头

continue;

int ny = e_y + dy[i];

int nx = e_x + dx[i];

if (ny = 4)

continue;

if (nx = 4)

continue;

path.push_back(direction[i]);

swap(T[ny][nx], T[e_y][e_x]);

swap(ny, e_y);

swap(nx, e_x);

if (dfs(current_steps + 1, i, bound))

return true;

swap(ny, e_y);

swap(nx, e_x);

swap(T[ny][nx], T[e_y][e_x]);

path.pop_back();

}

return false;

}

bool ida_star()

{

for (int limit = h(); limit <= MAX_N; ++limit)

{

if (dfs(0, -1, limit))

return true;

}

return false;

}

bool solvable()

{

int N = 0;

bool occur[16] = {false};

for (int y = 0; y 

{

for (int x = 0; x 

{

if (T[y][x] == 0)

{

e_y = y;

e_x = x;

}

else

{

N += count(occur + 1, occur + T[y][x], false);

occur[T[y][x]] = true;

}

}

}

return ((N + (e_y + 1)) & 1) == 0;  // N + e 为偶数,则当前局面有解,否则无解

}

int main()

{

#ifndef ONLINE_JUDGE

freopen("in.txt", "r", stdin);

#endif

int N;

scanf("%d", &N);

while (N--)

{

for (int y = 0; y 

{

for (int x = 0; x 

{

scanf("%d", &T[y][x]);

}

}

path.clear();

if (!solvable() || !ida_star())

{

puts("This puzzle is not solvable.");

}

else

{

printf("%s\n", path.c_str());

}

}

#ifndef ONLINE_JUDGE

fclose(stdin);

#endif

return 0;

}

a9e1894c4c74c37e88a5e00012c70baa.png

Reference

https://amoshyc.github.io/ojsolution-build/uva/p10181.html

这篇关于c语言15-puzzle解法,UVa 10181 15-Puzzle Problem 题解《挑战程序设计竞赛》的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/832889

相关文章

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

跨国公司撤出在华研发中心的启示:中国IT产业的挑战与机遇

近日,IBM中国宣布撤出在华的两大研发中心,这一决定在IT行业引发了广泛的讨论和关注。跨国公司在华研发中心的撤出,不仅对众多IT从业者的职业发展带来了直接的冲击,也引发了人们对全球化背景下中国IT产业竞争力和未来发展方向的深思。面对这一突如其来的变化,我们应如何看待跨国公司的决策?中国IT人才又该如何应对?中国IT产业将何去何从?本文将围绕这些问题展开探讨。 跨国公司撤出的背景与

csu 1446 Problem J Modified LCS (扩展欧几里得算法的简单应用)

这是一道扩展欧几里得算法的简单应用题,这题是在湖南多校训练赛中队友ac的一道题,在比赛之后请教了队友,然后自己把它a掉 这也是自己独自做扩展欧几里得算法的题目 题意:把题意转变下就变成了:求d1*x - d2*y = f2 - f1的解,很明显用exgcd来解 下面介绍一下exgcd的一些知识点:求ax + by = c的解 一、首先求ax + by = gcd(a,b)的解 这个

poj 3974 and hdu 3068 最长回文串的O(n)解法(Manacher算法)

求一段字符串中的最长回文串。 因为数据量比较大,用原来的O(n^2)会爆。 小白上的O(n^2)解法代码:TLE啦~ #include<stdio.h>#include<string.h>const int Maxn = 1000000;char s[Maxn];int main(){char e[] = {"END"};while(scanf("%s", s) != EO

uva 10055 uva 10071 uva 10300(水题两三道)

情歌两三首,水题两三道。 好久没敲代码了为暑假大作战热热身。 uva 10055 Hashmat the Brave Warrior 求俩数相减。 两个debug的地方,一个是longlong,一个是输入顺序。 代码: #include<stdio.h>int main(){long long a, b;//debugwhile(scanf("%lld%lld", &

poj 3259 uva 558 Wormholes(bellman最短路负权回路判断)

poj 3259: 题意:John的农场里n块地,m条路连接两块地,w个虫洞,虫洞是一条单向路,不但会把你传送到目的地,而且时间会倒退Ts。 任务是求你会不会在从某块地出发后又回来,看到了离开之前的自己。 判断树中是否存在负权回路就ok了。 bellman代码: #include<stdio.h>const int MaxN = 501;//农场数const int

poj 2349 Arctic Network uva 10369(prim or kruscal最小生成树)

题目很麻烦,因为不熟悉最小生成树的算法调试了好久。 感觉网上的题目解释都没说得很清楚,不适合新手。自己写一个。 题意:给你点的坐标,然后两点间可以有两种方式来通信:第一种是卫星通信,第二种是无线电通信。 卫星通信:任何两个有卫星频道的点间都可以直接建立连接,与点间的距离无关; 无线电通信:两个点之间的距离不能超过D,无线电收发器的功率越大,D越大,越昂贵。 计算无线电收发器D

科研绘图系列:R语言扩展物种堆积图(Extended Stacked Barplot)

介绍 R语言的扩展物种堆积图是一种数据可视化工具,它不仅展示了物种的堆积结果,还整合了不同样本分组之间的差异性分析结果。这种图形表示方法能够直观地比较不同物种在各个分组中的显著性差异,为研究者提供了一种有效的数据解读方式。 加载R包 knitr::opts_chunk$set(warning = F, message = F)library(tidyverse)library(phyl

uva 10387 Billiard(简单几何)

题意是一个球从矩形的中点出发,告诉你小球与矩形两条边的碰撞次数与小球回到原点的时间,求小球出发时的角度和小球的速度。 简单的几何问题,小球每与竖边碰撞一次,向右扩展一个相同的矩形;每与横边碰撞一次,向上扩展一个相同的矩形。 可以发现,扩展矩形的路径和在当前矩形中的每一段路径相同,当小球回到出发点时,一条直线的路径刚好经过最后一个扩展矩形的中心点。 最后扩展的路径和横边竖边恰好组成一个直