题意:有个#字型的棋盘,2行2列,一共24个格。
每个格子是1或2或3,一共8个1,8个2,8个3.
有A~H一共8种合法操作,比如A代表把A这一列向上移动一个,最上面的格会补到最下面。
求:使中心8个格子数字一致的最少步骤,要输出具体的操作步骤及最终中心区域的数字。如果有多个解,输出字典序最小的操作步骤。
思路:这个题目可以使用迭代加深搜索,时间复杂度也完全足够,这个方法的关键其实就是估价函数,也就是如果当前已经进行的操作次数,加上还需要的最小次数已经超过了当前的迭代层数就return,整个代码还是比较好写的。
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <fstream>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>
#include <sstream>
#include <list>
#define MAXN 210
#define INF 10000000
#define MOD 1000000007
#define LL long long
#define pi acos(-1.0)
using namespace std;
int board[MAXN][MAXN] = {{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 check_order[] = {6, 7, 8, 11, 12, 15, 16, 17};
int arr[MAXN];
char order[MAXN];
int falut_num() {
int ans1 = 0, ans2 = 0, ans3 = 0;
for (int i = 0; i < 8; ++i) {
if (arr[check_order[i]] == 1)
ans1++;
else if (arr[check_order[i]] == 2)
ans2++;
else
ans3++;
}
return 8 - max(max(ans1, ans2), ans3);
}
bool check() {
for (int i = 0; i < 8; ++i) {
if (arr[check_order[i]] != arr[check_order[0]])
return false;
}
return true;
}
bool dfs(int x, int maxn) {
if (x + falut_num() > maxn)
return false;
if (check())
return true;
int brr[MAXN];
int temp[MAXN];
memcpy(brr, arr, sizeof(arr));
for (int i = 0; i < 8; ++i) {
int cnt = 0;
for (int j = 1; j < 7; ++j)
temp[cnt++] = arr[board[i][j]];
temp[cnt++] = arr[board[i][0]];
for (int j = 0; j < 7; ++j) {
arr[board[i][j]] = temp[j];
}
order[x] = (char)(i + 'A');
if (dfs(x + 1, maxn))
return true;
memcpy(arr, brr, sizeof(brr));
}
return false;
}
int main() {
std::ios::sync_with_stdio(false);
while (cin >> arr[0] && arr[0]) {
for (int i = 1; i < 24; ++i)
cin >> arr[i];
if (check()) {
cout << "No moves needed\n";
cout << arr[6] << endl;
} else {
int maxn = 0;
while (true) {
if (dfs(0, maxn))
break;
maxn++;
}
order[maxn] = '\0';
cout << order << endl;
cout << arr[6] << endl;
}
}
return 0;
}
/*
1 1 1 1 3 2 3 2 3 1 3 2 2 3 1 2 2 2 3 1 2 1 3 3
1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3
0
*/