题目意思:hdu2821,给定一张图,图上有些障碍物,将球放在没有障碍物的起始位置,球能上下左右移动,但不能滚出图外。移动时撞到障碍物可将障碍物的数量减一并推向下一位置,如果下一位置同样有障碍物则该位置障碍物数量可叠加。注意推动障碍物必须与障碍物至少有一个点的间隔,否则不能推动障碍物。求起始位置及移动的明细。
解题思路:模拟+dfs,注意障碍物可推出图外,因此可将数组稍微设大一点,可减少代码量及相关判断。
代码明细:
//probID: hdu2821
//author: WiselyQY
//date: 2020-12-29
#include <bits/stdc++.h>
using namespace std;
int g[30][30],m,n,ok,ansx,ansy;
string ans;
const int dx[]={1,0,-1,0}, dy[]={0,1,0,-1};
const char dir[]={'D','R','U','L'};
int allClear()
{
for(int i=1; i<=m; i++)
for(int j=1; j<=n; j++)
if(g[i][j]) return 0;
return 1;
}
int in(int x, int y)
{
return x>=1 && x<=m && y>=1 && y<=n;
}
//从(x,y)位置出发,方向为k(0~3代表DRUL),返回0代表该方向不可行,返回1代表该方向可行,移动后新位置为(nx,ny)
int check(const int x, const int y, const int k, int& nx, int& ny)
{
nx=x+dx[k]; ny=y+dy[k];
if(in(nx,ny) && g[nx][ny]) return 0;
nx+=dx[k]; ny+=dy[k];
while(in(nx,ny) && !g[nx][ny]) {nx+=dx[k]; ny+=dy[k];}
if(nx<1 || nx>m || ny<1 || ny>n) return 0;
else
{
g[nx+dx[k]][ny+dy[k]]+=(g[nx][ny]-1);
g[nx][ny]=0;
return 1;
}
}
void dfs(int x, int y)
{
if(ok) return;
if(allClear())
{
ok=1;
cout<<ansx-1<<endl<<ansy-1<<endl<<ans<<endl;
return;
}
int gn[30][30];
string str;
memcpy(gn,g,sizeof(g));
str=ans;
//DRUL四个方向分别尝试
for(int i=0; i<4; i++)
{
int nx,ny;
if(check(x,y,i,nx,ny))
{
ans+=dir[i];
dfs(nx,ny);
memcpy(g,gn,sizeof(gn));
ans=str;
}
}
}
int main()
{
clock_t start,end;
start=clock();
#ifndef ONLINE_JUDGE
freopen(R"(D:\code\hdu\2821\in.txt)","r",stdin);
#endif
char ch[30][30];
while(cin>>n>>m)
{
for(int i=1; i<=m; i++)
for(int j=1; j<=n; j++)
{
cin>>ch[i][j];
if(ch[i][j]=='.') g[i][j]=0;
else g[i][j]=ch[i][j]-'a'+1;
}
ans="";
ok=0;
int gn[30][30];
memcpy(gn,g,sizeof(g));
for(int i=1; i<=m; i++)
{
if(ok) break;
ansx=i;
for(int j=1; j<=n; j++)
{
if(ok) break;
ansy=j;
if(!g[i][j])
{
dfs(i,j);
memcpy(g,gn,sizeof(gn));
}
}
}
}
end=clock();
//printf("time=%lfs\n",(double)(end-start)/1000);
return 0;
}