搞了一整个晚上,终于把这道神题调通了,真心有点复杂,涉及到哈希查重,广搜,深搜,虽然调通了但是思路还是有些冗杂,代码页不够简洁,敲键盘敲得手都麻了,先把代码粘上来吧。做的时候要进行适当剪枝,对于那种有单个彩色方块的状态,已经不可能再产生解决方案了,直接剪掉,可以提高效率,一开始一直run time error,后来发现是读数据的格式有问题,这种每一组数据中间有空行的数据格式还是用gets配合sscanf的形式读取数据最保险,以后要注意了。
#include <stdio.h>
#include <set>
#include <queue>
#include <list>
#include <map>
#include <string.h>
using namespace std;
typedef unsigned char node_type;
typedef unsigned char DIRECTION;
#define RED 1
#define GREEN 2
#define BLUE 3
#define FLYER 4
#define MAX_ROW 13
#define MAX_COL 21
#define MAX_HASH_SIZE 2000003
#define UP 1
#define DOWN 2
#define LEFT 3
#define RIGHT 4
int max_row_g;
int max_col_g;
struct state
{
char m[MAX_ROW][MAX_COL]; //当前的状态
int step; //达到状态的步数
char solution[30]; //记录走过的路径
};
typedef int HASH_VALUE;
typedef struct state STATE;
map< HASH_VALUE, list<STATE> > hash_map;
bool operator < (const struct state &a, const struct state &b)
{
if(a.step > b.step)
return true;
if(a.step < b.step)
return false;
else
{
char buf_a[20];
char buf_b[20];
memcpy(buf_a, a.solution+1, a.step);
memcpy(buf_b, b.solution+1, a.step);
buf_a[a.step] = '\0';
buf_b[b.step] = '\0';
if(strcmp(buf_a, buf_b) > 0)
return true;
else
return false;
}
}
priority_queue< struct state > pq; //优先队列
int _hash(const struct state &sta)
{
int i, j;
unsigned int v;
v = 1;
for(i=1; i<=max_row_g; i++)
for(j=1; j<=max_col_g; j++)
v = v*39+sta.m[i][j];
return v%MAX_HASH_SIZE;
}
void print_arr(struct state &sta)
{
for(int i=1; i<=max_row_g; i++)
{
for(int j=1; j<=max_col_g; j++)
printf("%c", sta.m[i][j]);
printf("\n");
}
}
//把一种状态插入到哈希表里面
void insert_state2hash_table(struct state &sta)
{
int hv;
hv = _hash(sta);
hash_map[hv].push_back(sta);
}
bool is_visited(struct state &sta)
{
int hv;
hv = _hash(sta);
if(hash_map.find(hv) == hash_map.end())
return false;
list< STATE >::iterator it;
bool res = false;
int i, j;
for(it=hash_map[hv].begin(); it!=hash_map[hv].end(); it++)
{
bool f;
f = true; //是否完全一样
for(i=1; i<=max_row_g; i++)
for(j=1; j<=max_col_g; j++)
{
if(it->m[i][j] != sta.m[i][j])
{
f = false;
break;
}
}
if(f == true)
{
res = true; //在哈希表里面已经找到这种状态了
break;
}
}
return res;
}
//返回是否有方块移动过
bool blow(struct state &sta, DIRECTION direction)
{
int i, j, end;
bool moved = false;
switch(direction)
{
case UP:
{
for(i=1; i<=max_row_g; i++) //应该从最上面一行开始
for(j=1; j<=max_col_g; j++)
{
if(sta.m[i][j]!='#' && sta.m[i][j]!=' ') //可移动节点
{
for(end=i-1; end>=1; end--)
if(sta.m[end][j] != ' ')
break;
end++;
if(end != i)
{
sta.m[end][j] = sta.m[i][j];
sta.m[i][j] = ' ';
moved = true;
}
}
}
break;
}
case DOWN:
{
for(i=max_row_g; i>=1; i--) //应该从最下面一行开始
for(j=1; j<=max_col_g; j++)
{
if(sta.m[i][j]!='#' && sta.m[i][j]!=' ') //可移动节点
{
for(end=i+1; end<=max_row_g; end++)
if(sta.m[end][j] != ' ')
break;
end--;
if(end != i)
{
sta.m[end][j] = sta.m[i][j];
sta.m[i][j] = ' ';
moved = true;
}
}
}
break;
}
case LEFT:
{
for(j=1; j<=max_col_g; j++) //从最左边一列开始
for(i=1; i<=max_row_g; i++)
{
if(sta.m[i][j]!='#' && sta.m[i][j]!=' ') //可移动节点
{
for(end=j-1; end>=1; end--)
if(sta.m[i][end] != ' ')
break;
end++;
if(end != j)
{
sta.m[i][end] = sta.m[i][j];
sta.m[i][j] = ' ';
moved = true;
}
}
}
break;
}
case RIGHT:
{
for(j=max_col_g; j>=1; j--) //从最右边一列开始
for(i=1; i<=max_row_g; i++)
{
if(sta.m[i][j]!='#' && sta.m[i][j]!=' ') //可移动节点
{
for(end=j+1; end<=max_col_g; end++)
if(sta.m[i][end] != ' ')
break;
end--;
if(end != j)
{
sta.m[i][end] = sta.m[i][j];
sta.m[i][j] = ' ';
moved = true;
}
}
}
break;
}
}
return moved;
}
void dfs(struct state &sta, int i, int j, bool &has_delete, char delete_char, int last_count)
{
if(!(i>=1 && i<=max_row_g))
return;
if(!(j>=1 && j<=max_col_g))
return;
if(sta.m[i][j]==' ' || sta.m[i][j]=='@' || sta.m[i][j]=='#')
return;
if(sta.m[i][j] == delete_char)
{
if(last_count >= 1)
{
sta.m[i][j] = ' ';
has_delete = true;
}
dfs(sta, i-1, j, has_delete, delete_char, last_count+1);
dfs(sta, i+1, j, has_delete, delete_char, last_count+1);
dfs(sta, i, j-1, has_delete, delete_char, last_count+1);
dfs(sta, i, j+1, has_delete, delete_char, last_count+1);
}
else
{
return;
}
}
//消除掉相同颜色的方块, 返回有没有消除过相同颜色的方块
bool clear_gem(struct state &sta)
{
int i, j;
bool has_delete; //有没有消除过方块
bool res;
res = false;
for(i=1; i<=max_row_g; i++)
for(j=1; j<=max_col_g; j++)
{
has_delete = false;
dfs(sta, i, j, has_delete, sta.m[i][j], 0);
if(has_delete)
{
res = true;
sta.m[i][j] = ' ';
}
}
return res;
}
//判断是不是所有彩色方块消除完毕的状态
bool is_last_state(const struct state &sta)
{
int i, j;
int res;
res = true;
for(i=1; i<=max_row_g; i++)
for(j=1; j<=max_col_g; j++)
{
if(sta.m[i][j]=='1' || sta.m[i][j]=='2' || sta.m[i][j]=='3')
{
res = false;
break;
}
}
return res;
}
//查看有没有单个的彩色方块,有的话这种状态无解
bool can_solve(const struct state &sta)
{
int count1, count2, count3;
int i, j;
count1 = count2 = count3 = 0;
for(i=1; i<=max_row_g; i++)
for(j=1; j<=max_col_g; j++)
{
if(sta.m[i][j] == '1')
count1 ++;
else if(sta.m[i][j] == '2')
count2 ++;
else if(sta.m[i][j] == '3')
count3 ++;
}
if(count1==1 || count2==1 || count3==1)
return false;
return true;
}
void bfs()
{
struct state sta, sta_top;
int i, j, end;
while(!pq.empty())
{
memcpy(&sta_top, &(pq.top()), sizeof(struct state));
pq.pop();
if(is_last_state(sta_top))
{
for(i=1; i<=sta_top.step; i++)
printf("%c", sta_top.solution[i]);
printf("\n");
return;
}
//printf("pop: step=%d\n", sta_top.step);
//print_arr(sta_top);
//printf("\n");
//节点向下运动
memcpy(&sta, &sta_top, sizeof(struct state));
while(1)
{
if(!blow(sta, DOWN))
break;
if(!clear_gem(sta))
break;
}
if(!is_visited(sta))
{
sta.step = sta_top.step+1;
if(sta.step <=18 && can_solve(sta))
{
sta.solution[sta.step] = 'D';
pq.push(sta);
insert_state2hash_table(sta);
//printf("push DOWN:\n");
//print_arr(sta);
//printf("\n");
}
}
//节点向左运动
memcpy(&sta, &sta_top, sizeof(struct state));
while(1)
{
if(!blow(sta, LEFT))
break;
if(!clear_gem(sta))
break;
}
if(!is_visited(sta))
{
sta.step = sta_top.step+1;
if(sta.step <=18 && can_solve(sta))
{
sta.solution[sta.step] = 'L';
pq.push(sta);
insert_state2hash_table(sta);
//printf("push LEFT:\n");
//print_arr(sta);
//printf("\n");
}
}
//节点向右运动
memcpy(&sta, &sta_top, sizeof(struct state));
while(1)
{
if(!blow(sta, RIGHT))
break;
if(!clear_gem(sta))
break;
}
if(!is_visited(sta))
{
sta.step = sta_top.step+1;
if(sta.step <=18 && can_solve(sta))
{
sta.solution[sta.step] = 'R';
pq.push(sta);
insert_state2hash_table(sta);
//printf("push RIGHT:\n");
//print_arr(sta);
//printf("\n");
}
}
//节点向上运动
memcpy(&sta, &sta_top, sizeof(struct state));
while(1)
{
if(!blow(sta, UP))
break;
if(!clear_gem(sta))
break;
}
if(!is_visited(sta))
{
sta.step = sta_top.step+1;
if(sta.step <=18 && can_solve(sta))
{
sta.solution[sta.step] = 'U';
pq.push(sta);
insert_state2hash_table(sta);
//printf("push UP:\n");
//print_arr(sta);
//printf("\n");
}
}
}
printf("-1\n");
}
void func(int m, int n, const struct state &sta)
{
max_row_g = m;
max_col_g = n;
hash_map.clear();
while(!pq.empty())
pq.pop();
pq.push(sta);
hash_map[_hash(sta)].push_back(sta);
bfs();
}
char buffer[100];
int main(void)
{
int N, m, n;
int i, j;
struct state sta;
//freopen("input.dat", "r", stdin);
gets(buffer);
sscanf(buffer, "%d", &N);
sta.step = 0;
while(N--)
{
gets(buffer);
sscanf(buffer, "%d %d", &m, &n);
for(i=1; i<=m; i++)
{
gets(sta.m[i]+1);
}
gets(buffer);
func(m, n, sta);
}
return 0;
}