您的位置:首页 > 其它

UVa 1343 旋转游戏(dfs+IDA*)

2017-01-24 10:25 501 查看


https://vjudge.net/problem/UVA-1343

题意:如图所示,一共有8个1,8个2和8个3,如何以最少的移动来使得中间8个格子都为同一个数。

思路:状态空间搜索问题。

用IDA*算法的话会比较快,而且代码比较简洁。

IDA*的关键就是要寻找一个估价函数h(),在这道题目中,每次移动最多只会使一个格子的数字正确,所以当maxd-d<h()时便可以剪枝。

#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;

int position[8][7] =    {
{ 0, 2, 6, 11, 15, 20, 22 }, { 1, 3, 8, 12, 17, 21, 23 },  //八个方向格子的坐标值
{ 10, 9, 8, 7, 6, 5, 4},  { 19, 18, 17, 16, 15, 14, 13 },
{23, 21, 17, 12, 8, 3, 1}, { 22, 20, 15, 11, 6, 2, 0 },
{13, 14, 15, 16, 17, 18, 19}, { 4, 5, 6, 7, 8, 9, 10 }
};

int goal[] = { 6, 7, 8, 11, 12, 15, 16, 17 }; //目标状态的坐标

int a[25];
char order[30];     //记录路径

bool is_goal()  //判断是否已达到目标状态
{
for (int i = 0; i < 7; i++)
{
if (a[goal[i]]!=a[goal[i + 1]])    return false;
}
return true;
}

int h()  //算出不匹配的最小值
{
int n1 = 0, n2 = 0, n3 = 0;
for (int i = 0; i < 8; i++)
{
if (a[goal[i]] == 1) n1++;
else if (a[goal[i]] == 2)  n2++;
else if (a[goal[i]] == 3)  n3++;
}
return 8 -max( max(n1, n2),n3);
}

void rotate(int k)  //往指定的方向移动
{
int temp = a[position[k][0]];
for (int i = 1; i < 7; i++)
{
a[position[k][i-1]] = a[position[k][i]];
}
a[position[k][6]] = temp;
}

bool dfs(int d, int maxd)
{
if (is_goal())    return true;
if (maxd - d < h())    return false;  //剪枝
int old[25];   //用来保存原来的序列
memcpy(old, a, sizeof(a));
for (int i = 0; i < 8; i++)
{
rotate(i); //往第i个方向移动
order[d] = i + 'A';
if (dfs(d + 1, maxd))  return true;
memcpy(a, old, sizeof(old)); //如果失败,则恢复原来序列
}
return false;
}

void solve()
{
if (is_goal())
{
cout << "No moves needed" << endl << a[6] << endl;
return;
}
for (int maxd = 1;; maxd++)
{
if (dfs(0, maxd))
{
order[maxd] = '\0';
cout << order << endl << a[6] << endl;
return;
}
}
}

int main()
{
//freopen("D:\\txt.txt", "r", stdin);
while (cin >> a[0] && a[0])
{
for (int i = 1; i < 24; i++)
cin >> a[i];
solve();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: