[题解] HDU 2128 Tempter of the Bone II(迭代加深)

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~~
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值