Pusher HDU - 2821
看网上的题解都差不多
我来发一篇自己写的dfs,
与网上大多写的dfs不同,是另一种dfs的写法
(感觉更好哦)
题意 有一个RC的方格,‘.’代表空地,‘az’分别代表该处有126个箱子,某人可以从距离箱子至少一个空格处推箱子,推一次此处少一个箱子,如果这个格还有其他箱子,则和它下一个格的箱子合并或到下一个格,朝着某个方向一直推到边界或者遇到箱子不能推为止(即箱子数多于1的堆在边界)才可以换方向,任意输出一种可以把箱子推完的方案,输出推箱子时起点的位置以及推箱子时的方向。
注意:①起点不能有箱子。②必须要隔一个位置才能碰。③碰的箱子在边上时,如果剩下的箱子移出边界,则视为违法的,需要换个方向
思路 细节dfs,先预处理下,将’.'换成数字0,abcd换成对应数字即可
踩坑 别用getchar()一个个读入处理,容易出错!!!
小技巧 双重循环还可以这样退出!!!
这道题主要是细节,细节都写代码里了,看代码吧
#include<iostream>
#include<string>
#pragma comment(linker, "/STACK:102400000,102400000")//解决递归函数多次调用栈溢出问题
using namespace std;
#define Debug(x) cout<<#x<<':'<<x<<endl
typedef long long ll;
#define INF 0x7fffffff//10^9级别,不到2^32
ll gra[33][33],dir[11][2]={0,0,-1,0,0,1,1,0,0,-1};//方向数组
char ar[11]={'0','U','R','D','L'};//记录路径
ll c,r;
string outs;
ll dfs(ll x,ll y,ll cnt,string s,ll d,ll b){//
//x,y是推箱人的坐标,cnt是剩余箱子数量,s是推箱子的路径方向
//d为1 2 3 4,分别表示上右下左,
//b为间隙数,当b>=2时,表明经过了至少一个间隙,才能碰
//dfs找到一条能把箱子都清楚的路径时返回1,否则返回0
if(x<1 || x>r || y<1 || y>c) return 0;//当前越界
if(cnt==0){//箱子全部清除
outs=s;
return 1;
}
if(d==0){//推到箱子停止时,d为0,选择方向
for(ll i=1;i<=4;i++){
if(dfs(x+dir[i][0],y+dir[i][1],cnt,s+ar[i],i,b+1)) return 1;
}
}
else{//d不为0
if(gra[x][y]==0){//当前位置是道路
if(dfs(x+dir[d][0],y+dir[d][1],cnt,s,d,b+1)) return 1;
}
else{//当前位置是与木块重合,即撞到木块,
if(b<2) return 0;//如果没有间隙,即必须要隔一个位置才能碰
if(x+dir[d][0]<1 || x+dir[d][0]>r || y+dir[d][1]<1 || y+dir[d][1]>c){//如果后面是边界
ll t=gra[x][y];
if(t>1) return 0;//因为后面是边界,且箱子数比1多
gra[x][y]=0;
if(dfs(x,y,cnt-1,s,0,0)) return 1;
gra[x][y]=1;//回溯
}
else{//如果后面不是边界
ll t=gra[x][y];
gra[x][y]=0;
gra[x+dir[d][0]][y+dir[d][1]]+=t-1;
if(dfs(x,y,cnt-1,s,0,0)) return 1;
gra[x][y]=t;//回溯
gra[x+dir[d][0]][y+dir[d][1]]+=1-t;
}
}
}
return 0;
}
int main(){
while(scanf("%lld%lld",&c,&r)==2){
ll cnt=0;
char br[33];
for(ll i=1;i<=r;i++){//预处理
scanf("%s",br+1);//注意!!!这里别用getchar()一个个字符处理读入,很可能因为数据有多余空格出错!!!
for(ll j=1;j<=c;j++){
if(br[j]=='.') gra[i][j]=0;
else{
gra[i][j]=br[j]-'a'+1;
}
cnt+=gra[i][j];
}
}
string s;
for(ll i=1;i<=r;i++){
for(ll j=1;j<=c;j++){//枚举每个点作为起点
if(gra[i][j]!=0) continue;//起点不能有箱子
if(dfs(i,j,cnt,s,0,0)){
cout<<i-1<<"\n";
cout<<j-1<<"\n";
cout<<outs<<"\n";
i=r+1;j=c+1;//双重循环可以这样子退出!!!
}
}
}
}
return 0;
}