hdu2821 Pusher
题意:n*m的格子上有一些方块放在某些格子上,一个格子可能有几个方块,用'a'-'z'来表示方块数量。
初始的时候可以选择任意空地作为Pusher初始点,Pusher选择一个方向,然后向这个方向前进直到遇到有方块的格子,Pusher把这个格子的方块清除一个,并把它向前推一格(向前不能出界),如果前面一格有方块,那么这些方合起来放在这个格子中。Pusher和有方块的格子之间至少要有一个空地才能推动
分析:直接dfs,因为是special judge 找到一组解即可。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream>
#define N 30
using namespace std;
char dd[10] = "RDLU";
char map[N][N], rr[1000];
int n, m, flag, s;
int dir[4][2] = {{0, 1}, {1, 0}, {0, -1}, { -1, 0}};
bool check(int x, int y)
{
if(x < 0 || x >= n || y < 0 || y >= m)
return false;
return true;
}
void dfs(int x, int y, int p)
{
int i, j, t;
if (p >= s)//所有的block清除了
{
rr[p] = 0;
flag = 1;
return;
}
for (int k = 0; k < 4; k++)
{
i = x + dir[k][0];
j = y + dir[k][1];
if (!check(i, j) || map[i][j])
continue;
while (check(i, j) && !map[i][j])
i += dir[k][0], j += dir[k][1];
if (!check(i + dir[k][0], j + dir[k][1])) //到达棋盘的边缘也是不能push的
continue;
t = map[i][j];
map[i+dir[k][0]][j+dir[k][1]] += t - 1;
map[i][j] = 0;//原先的位置清空
rr[p] = dd[k];//保存路径
dfs(i, j, p + 1);
if (flag) return;
map[i+dir[k][0]][j+dir[k][1]] -= t - 1;//回溯时要还原
map[i][j] = t;
}
}
int main()
{
while (scanf("%d%d", &m, &n) == 2)
{
flag = s = 0;
int i, j;
for (i = 0; i < n; i++)
{
scanf("%s", map[i]);
for (j = 0; j < m; j++)
{
if (map[i][j] == '.') map[i][j] = 0;
else map[i][j] -= 'a' - 1;
s += map[i][j];
}
}
for (i = 0; i < n; i++) if (!flag)
for (j = 0; j < m; j++)
{
dfs(i, j, 0);
if (flag)
{
printf("%d\n%d\n", i, j);
puts(rr);
break;
}
}
}
}