这是建立树的代码,时间仓促没有进行很好的优化。
可以测试一下,初始化的时间在我的机器上是300ms。主要是为了节省空间而进行的运算比较耗时,换成位运算可以更快但内存消耗要增加一半。
输入只需直接输入成一行即可。比如
0 1 2
3 4 5
6 7 8
输入的格式为012345678。其它格式将被认为是无意义数据,程序退出。输出为每次该移动的方向。
程序代码:
#include<stdio.h>
#define UP 1
#define LEFT 2
#define DOWN 3
#define RIGHT 4
#define COUNT 362880
typedef struct
{
int state;
int father_id;
char direction;
char zr;
char zc;
}STATE;
STATE states[COUNT];
void GenarateState(STATE **ss, int *e, int from, int n)
{
int i, j, t;
if(from >= n)
{
for(i = 0; i < n; i++)
{
(*ss)->state = (*ss)->state * 10 + e[i];
if(e[i] == 0){ (*ss)->zr = i / 3; (*ss)->zc = i % 3;}
}
(*ss)++;
return;
}
for(i = from; i < n; i++)
{
for(t = e[i], j = i; j > from; j--) e[j] = e[j - 1];
e[from] = t;
GenarateState(ss, e, from + 1, n);
for(t = e[from], j = from; j < i; j++) e[j] = e[j + 1];
e[i] = t;
}
}
int SwapDigit(int state, int i, int j)
{
int e[] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000};
int ai, aj;
ai = state / e[i] % 10;
aj = state / e[j] % 10;
return state - ai * e[i] - aj * e[j] + ai * e[j] + aj * e[i];
}
int GetStateIndex(STATE *s, int state)
{
int i, j, d;
for(i = 0, j = COUNT - 1; i <= j;)
{
d = (i + j) >> 1;
if(s[d].state == state) return d;
if(s[d].state < state) i = d + 1; else j = d - 1;
}
return -1;
}
int GetNextStateIndex(STATE * s0, STATE * s, int direction)
{
int i, j;
i = s->zr;
j = s->zc;
switch(direction)
{
case UP: if(i > 0) return GetStateIndex(s0, SwapDigit(s->state, 8 - (i - 1) * 3 - j, 8 - i * 3 - j)); break;
case LEFT: if(j > 0) return GetStateIndex(s0, SwapDigit(s->state, 8 - i * 3 - j + 1, 8 - i * 3 - j)); break;
case DOWN: if(i < 2) return GetStateIndex(s0, SwapDigit(s->state, 8 - (i + 1) * 3 - j, 8 - i * 3 - j)); break;
case RIGHT: if(j < 2) return GetStateIndex(s0, SwapDigit(s->state, 8 - i * 3 - j - 1, 8 - i * 3 - j)); break;
}
return -1;
}
void InitStates(STATE * s)
{
int si[COUNT], e[] = {0, 1, 2, 3, 4, 5, 6, 7, 8}, i, j, d, fid;
STATE * ts;
ts = s;
GenarateState(&ts, e, 0, 9);
si[0] = GetStateIndex(s, 123456780);
s[si[0]].father_id = si[0];
for(i = 0, j = 1; i < j; i++)//这个循环是建立最小生成树的主要逻辑代码,其它都是辅助完成状态的计算和转移
for(d = 1; d <= 4; d++)
{
fid = GetNextStateIndex(s, s + si[i], d);
if(fid >= 0 && s[fid].direction == 0)
{
s[fid].father_id = si[i];
s[fid].direction = d;
si[j++] = fid;
}
}
}
void PrintStep(STATE * s, int state)
{
int root_id, id;
root_id = GetStateIndex(s, 123456780);
id = GetStateIndex(s, state);
if(s[id].direction == 0)
{
printf("此状态无解\n");
return;
}
while(id != root_id)
{
switch(s[id].direction)
{
case UP: printf("上"); break;
case LEFT: printf("左"); break;
case DOWN: printf("下"); break;
case RIGHT: printf("右"); break;
}
id = s[id].father_id;
}
}
int main()
{
int state;
InitStates(states);
for(;;state = 0)
{
printf("\n\n输入初始状态(输入无意义则退出):");
scanf("%d", &state);
if(GetStateIndex(states, state) < 0) break;
PrintStep(states, state);
}
return 0;
}
[
本帖最后由 beyondyf 于 2012-3-7 22:18 编辑 ]