hdu 2128(bfs)

题目链接 :http://acm.hdu.edu.cn/showproblem.php?pid=2128

思路:这题判重比较麻烦,我是这样做的:每个状态记录炸弹数目以及爆破点的坐标映射,还要有一个访问数组来标记已经取过的炸弹的位置(下次经过就不能再取了),由于要求时间最短,可以考虑优先队列。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<queue>
 6 using namespace std;
 7 struct Node {
 8     int x,y,time;
 9     bool operator < (const Node &p) const {
10         return p.time<time;
11     }
12     int key;//***
13     int count;//所有爆破位置的坐标的映射(有点瞎搞的味道,hd数据弱,应该也会有冲突的吧)
14     bool visited[9][9];//记录每个状态爆破的位置,有可能重复走
15 } st;
16 char map[9][9];
17 bool mark[9][9][66][2222];//标记
18 int n,m;
19 int dir[4][2]= {{-1,0},{1,0},{0,-1},{0,1}};
20 int ex,ey;
21 
22 bool bfs() {
23     memset(mark,false,sizeof(mark));
24     mark[st.x][st.y][st.key][st.count]=true;
25     Node p,q;
26     priority_queue<Node>Q;
27     Q.push(st);
28     while(!Q.empty()) {
29         p=Q.top();
30         Q.pop();
31         if(p.x==ex&&p.y==ey) {
32             printf("%d\n",p.time);
33             return true;
34         }
35         for(int i=0; i<4; i++) {
36             q=p;
37             q.x=p.x+dir[i][0];
38             q.y=p.y+dir[i][1];
39             q.time=p.time+1;
40             if(q.x<1||q.x>n||q.y<1||q.y>m)continue;
41             if(map[q.x][q.y]=='.') {
42                 if(!mark[q.x][q.y][q.key][q.count]) {
43                     mark[q.x][q.y][q.key][q.count]=true;
44                     Q.push(q);
45                 }
46             } else if(map[q.x][q.y]=='X') {
47                 if(!q.visited[q.x][q.y]) {
48                     if(q.key>0) {
49                         q.key--,q.count+=(q.x*q.y+8*(q.x+q.y));
50                         q.time++;
51                         q.visited[q.x][q.y]=true;
52                         if(!mark[q.x][q.y][q.key][q.count]) {
53                             mark[q.x][q.y][q.key][q.count]=true;
54                             Q.push(q);
55                         }
56                     }
57                 } else if(!mark[q.x][q.y][q.key][q.count]) {
58                     mark[q.x][q.y][q.key][q.count]=true;
59                     Q.push(q);
60                 }
61             } else {
62                 if(!q.visited[q.x][q.y]) {
63                     q.visited[q.x][q.y]=true;
64                     q.key+=map[q.x][q.y]-'0';
65                 }
66                 if(!mark[q.x][q.y][q.key][q.count]) {
67                     mark[q.x][q.y][q.key][q.count]=true;
68                     Q.push(q);
69                 }
70             }
71         }
72     }
73     return false;
74 }
75 
76 
77 int main() {
78  //  freopen("1.txt","r",stdin);
79     while(scanf("%d%d",&n,&m),(n+m)) {
80         for(int i=1; i<=n; i++) {
81             scanf("%s",map[i]+1);
82             for(int j=1; j<=m; j++) {
83                 if(map[i][j]=='S') {
84                     map[i][j]='.';
85                     st.x=i;
86                     st.y=j;
87                     st.time=st.key=st.count=0;
88                     memset(st.visited,false,sizeof(st.visited));
89                     st.visited[st.x][st.y]=true;
90                 } else if(map[i][j]=='D') {
91                     map[i][j]='.';
92                     ex=i,ey=j;
93                 }
94             }
95         }
96         if(!bfs())puts("-1");
97     }
98     return 0;
99 }
View Code

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值