这道题用启发式搜索,我在北大网站上可以过,杭电网站上超时,看来杭电的数据有点变态了。
#include <stdio.h>
#include <set>
#include <queue>
#include <string.h>
using namespace std;
int target_pos[10][2];
char buf[100];
struct state
{
int pos_i, pos_j;
unsigned char m[4][4];
int step;
int weight;
char solution[100];
};
priority_queue<struct state> pq;
set<unsigned int> hash_table;
bool operator < (const struct state &a, const struct state &b)
{
if(a.weight > b.weight)
return true;
else if(a.weight < b.weight)
return false;
else
{
if(a.step > b.step)
return true;
else
return false;
}
}
unsigned int _hash(const struct state &sta)
{
unsigned int sum;
int cifang, i, j;
cifang = 1;
sum = 0;
for(i=1; i<=3; i++)
for(j=1; j<=3; j++)
{
sum += cifang * sta.m[i][j];
cifang *= 10;
}
return sum;
}
void init_target_pos()
{
target_pos[1][0] = 1;
target_pos[1][1] = 1;
target_pos[2][0] = 1;
target_pos[2][1] = 2;
target_pos[3][0] = 1;
target_pos[3][1] = 3;
target_pos[4][0] = 2;
target_pos[4][1] = 1;
target_pos[5][0] = 2;
target_pos[5][1] = 2;
target_pos[6][0] = 2;
target_pos[6][1] = 3;
target_pos[7][0] = 3;
target_pos[7][1] = 1;
target_pos[8][0] = 3;
target_pos[8][1] = 2;
target_pos[9][0] = 3;
target_pos[9][1] = 3;
}
int _abs(int x)
{
return x>0 ? x : -1*x;
}
void get_weight(struct state &sta)
{
int i, j;
int sum;
sum = 0;
for(i=1; i<=3; i++)
for(j=1; j<=3; j++)
{
if(sta.m[i][j] <= 8)
{
sum += _abs(i-target_pos[sta.m[i][j]][0]);
sum += _abs(j-target_pos[sta.m[i][j]][1]);
}
}
sta.weight = sum+sta.step;
}
bool find_solution;
void print_arr(const struct state &sta)
{
int i, j;
for(i=1; i<=3; i++)
{
for(j=1; j<=3; j++)
printf("%d ", sta.m[i][j]);
printf("\n");
}
}
void bfs()
{
struct state sta, sta_top;
int hv;
while(!pq.empty())
{
memcpy(&sta_top, &(pq.top()), sizeof(struct state));
pq.pop();
//printf("step=%d weight=%d\n", sta_top.step, sta_top.weight);
//print_arr(sta_top);
if(_hash(sta_top) == 987654321)
{
sta_top.solution[sta_top.step+1] = '\0';
printf("%s\n", sta_top.solution+1);
find_solution = true;
break;
}
memcpy(&sta, &sta_top, sizeof(struct state));
if(sta.pos_i >= 2)
{
sta.m[sta.pos_i][sta.pos_j] = sta.m[sta.pos_i-1][sta.pos_j];
sta.m[sta.pos_i-1][sta.pos_j] = 9;
hv = _hash(sta);
if(hash_table.find(hv) == hash_table.end())
{
sta.pos_i--;
sta.step++;
sta.solution[sta.step] = 'u';
get_weight(sta);
hash_table.insert(hv);
pq.push(sta);
}
}
memcpy(&sta, &sta_top, sizeof(struct state));
if(sta.pos_i <= 2)
{
sta.m[sta.pos_i][sta.pos_j] = sta.m[sta.pos_i+1][sta.pos_j];
sta.m[sta.pos_i+1][sta.pos_j] = 9;
hv = _hash(sta);
if(hash_table.find(hv) == hash_table.end())
{
sta.pos_i++;
sta.step++;
sta.solution[sta.step] = 'd';
get_weight(sta);
hash_table.insert(hv);
pq.push(sta);
}
}
memcpy(&sta, &sta_top, sizeof(struct state));
if(sta.pos_j >= 2)
{
sta.m[sta.pos_i][sta.pos_j] = sta.m[sta.pos_i][sta.pos_j-1];
sta.m[sta.pos_i][sta.pos_j-1] = 9;
hv = _hash(sta);
if(hash_table.find(hv) == hash_table.end())
{
sta.pos_j--;
sta.step++;
sta.solution[sta.step] = 'l';
get_weight(sta);
hash_table.insert(hv);
pq.push(sta);
}
}
memcpy(&sta, &sta_top, sizeof(struct state));
if(sta.pos_j <= 2)
{
sta.m[sta.pos_i][sta.pos_j] = sta.m[sta.pos_i][sta.pos_j+1];
sta.m[sta.pos_i][sta.pos_j+1] = 9;
hv = _hash(sta);
if(hash_table.find(hv) == hash_table.end())
{
sta.pos_j++;
sta.step++;
sta.solution[sta.step] = 'r';
get_weight(sta);
hash_table.insert(hv);
pq.push(sta);
}
}
}
}
void func(struct state &sta)
{
init_target_pos();
hash_table.clear();
while(!pq.empty())
pq.pop();
get_weight(sta);
hash_table.insert(_hash(sta));
pq.push(sta);
find_solution = false;
bfs();
if(!find_solution)
printf("unsolvable\n");
}
int main(void)
{
int i;
int ii, jj;
struct state sta;
//freopen("input.dat", "r", stdin);
while(gets(buf))
{
if(buf[0] == '\0')
break;
ii = jj = 1;
for(i=0; i<=strlen(buf); i++)
{
if(buf[i]>='1'&&buf[i]<='8')
{
sta.m[ii][jj] = buf[i]-'0';
jj++;
if(jj == 4)
{
ii++;
jj = 1;
}
}
else if(buf[i] == 'x')
{
sta.m[ii][jj] = 9;
sta.pos_i = ii;
sta.pos_j = jj;
jj++;
if(jj == 4)
{
ii++;
jj = 1;
}
}
}
sta.step = 0;
func(sta);
}
return 0;
}