HDU 2128 Tempter of the Bone II(迭代加深)
刚刚看到这道题目时,很开心啊:好水啊~这不就是一个BFS么,太简单了。
然而,当我发现一个点可以重复访问并且有可能更优时,我掐指一算,WTF,这能过?果断转向DFS,但是将所有结果全部找出来再判断绝对的TLE。怎么办?
So,这就成为了结合BFS与DFS优点的迭代加深算法发威的时候了!
好好好,既然知道算法了,来一发题解装13,然而,等待着我的是:WA WA WA WA WA…
WTF?为毛?
经过三个小时的细心查找,原来是题目描述不清。Doggie炸掉一个墙是需要在原地停留一秒的!!!(泪如雨下)好吧就这样吧,交上去终于开心的AC了。
来讲讲迭代算法。迭代算法其实就是在普通DFS的外面套一层搜索下界,以保证搜索得到的是最优解。特别适合那些不知道搜索下界有可能无限搜搜搜搜搜的题目。具体内容让我们来看代码。
代码如下:
#include <bits/stdc++.h>
using namespace std;
char MAP[10][10];
int sum[10][10];
int mo[4][2]={{1,0},{0,1},{0,-1},{-1,0}};
int n,m,stx,sty,sgx,sgy;
bool flag=0;
void search(int x,int y,int num,int total,int depth) {
int qwe,i;char ch;
if(total==depth) { //前面的搜索可以保证没有可行解,so如果在最后一层搜到结果就输出啦~
if(MAP[x][y]=='D') flag=1;
return;
}
int nx,ny;
sum[x][y]=num; //sum用来保存每一个点的最大炸药数,因为炸药当然是越多越好啦!其实就是为了方便判重。。
if(abs(x-sgx)+abs(y-sgy)>depth-total) return; //这里是曼哈顿局距离的可行性剪枝
for(i=0;i<=3;i++) {
nx=x+mo[i][0];
ny=y+mo[i][1];
if(nx<0 || nx>=n || ny<0 || ny>=m || sum[nx][ny]>=num) {continue;}
if(MAP[nx][ny]=='X' && num>=1) { //如果手头上还有炸药就把墙炸了
MAP[nx][ny]='.';
qwe=sum[nx][ny];
search(nx,ny,num-1,total+2,depth);
MAP[nx][ny]='X';
sum[nx][ny]=qwe;
if(flag)
{return;}
}
else if(MAP[nx][ny]=='.' || MAP[nx][ny]=='D' || MAP[nx][ny]=='S') {
qwe=sum[nx][ny];
search(nx,ny,num,total+1,depth);
sum[nx][ny]=qwe;
if(flag)
{return;}
}
else if(MAP[nx][ny]>='1' && MAP[nx][ny]<='9') { //将炸药“入库”
ch=MAP[nx][ny];
qwe=sum[nx][ny];
MAP[nx][ny]='.';
search(nx,ny,num+ch-'0',total+1,depth);
MAP[nx][ny]=ch;
sum[nx][ny]=qwe;
if(flag)
{return;}
}
}
return;
}
bool input() { //输入部分大家都懂的哈
int i,j,k;
memset(MAP,0,sizeof(MAP));
memset(sum,0,sizeof(sum));
scanf("%d%d\n",&n,&m);
if(n==0 && m==0) return false;
for(i=0;i<n;i++) {
for(j=0;j<m;j++) {
scanf("%c",&MAP[i][j]);
if(MAP[i][j]=='S') {
stx=i;
sty=j;
MAP[i][j]='.';
}
if(MAP[i][j]=='D') {
sgx=i;
sgy=j;
}
}
scanf("\n");
}
for(i=1;i<=100;i++) { //为了方便,我将迭代部分也放在了这里
for(j=0;j<n;j++) { //每次i自增,就让迭代的层数往下一层
for(k=0;k<m;k++) {//i超过100应该就没有解啦(我猜的)
sum[j][k]=-1;
}
}
search(stx,sty,0,0,i);
if(flag) {printf("%d\n",i);break;}
}
return true;
}
int main() {
int i;
while(1) {
flag=0;
if(!input()) {break;}
if(flag) continue;
printf("-1\n");
}
return 0;
}
最后来一波数据(来自HDU)
Input:
6 5
S.XX1
X.1X1
XX.X.
XXXXX
XXXXX
XXXDX
2 6
S.1XXD
1..XXX
4 4
S1X1
XXXX
XXDX
XXXX
6 2
S1
..
1X
XX
XX
DX
0 0
Output
17
9
8
9
From:Chlience
PS:有问题或者闲的蛋疼的朋友可以发邮件至steve_chl@qq.com或者私信我,欢迎骚扰O(∩_∩)O~~