原题:
http://poj.org/problem?id=3009
AC代码:
#include<iostream>
#include<algorithm>
#include<cstring>
#define INF 999999
using namespace std;
int s[21][21],move[4][2]={-1,0,0,1,1,0,0,-1},w,h,mins,sx,sy;
int main()
{
void solve();
while(cin>>w>>h,w||h)
{
mins=INF;
memset(s,0,sizeof(s));
for(int i=0;i<h;i++)
for(int j=0;j<w;j++)
{
cin>>s[i][j];
if(s[i][j]==2)
{
sx=i;
sy=j;
s[i][j]=0;//★★★★★★★★
}
}
solve();
}
return 0;
}
void solve()
{
void dfs(int,int,int);
dfs(sx,sy,1);
if(mins==INF)
cout<<-1<<endl;
else
cout<<mins<<endl;
}
void dfs(int x,int y,int step)
{
int in(int,int);
if(step>10)
return;
for(int i=0;i<4;i++)
{
int &dx=move[i][0];
int &dy=move[i][1];
int rx=x;
int ry=y;
if(s[rx+dx][ry+dy]==1)//紧挨着1 不能滑动
continue;
if(step>=mins)//这一条分支不是最优解
continue;//剪枝
while(in(rx+dx,ry+dy))//不越界 可以滑动
{
if(s[rx+dx][ry+dy]==0)//如果下一块是0 滑动
{
rx+=dx;
ry+=dy;
}
else if(s[rx+dx][ry+dy]==3)//下一块是3
{
mins=min(step,mins);
break;
}
else//下一块是1
{
s[rx+dx][ry+dy]=0;//击碎1
dfs(rx,ry,step+1);
s[rx+dx][ry+dy]=1;//复原击碎
break;
}
}
}
}
int in(int x,int y)
{
if(x>=0&&x<h&&y>=0&&y<w)
return 1;
else
return 0;
}
总结:
①cin或printf或INF不会影响AC 错了往别的方向想
②把思路再草稿纸捋清晰再开始编程
③判断是否越界可重开一个函数
④step放在函数中 避免放在深搜过程中 容易搞混
⑤要把起点设置成0 避免隐藏的麻烦
⑥一条分支如需对输入的内容改变 分支结束一定要复原 否则影响下面某个分支判断
⑦ int &dx=move[i][0]; 这样设置可以避免复杂的书写
⑧一块一判断 e.g.不要先判断元素1旁边是否为1(石头)且不越界才移动 再判断此分支直线的下一块是否为0 这样嵌套太多 非常麻烦
⑨注意break continue return区别