hdu--3442 Three Kingdoms(bfs+优先队列)

Description

Three Kingdoms is a funny game. Often Liu Bei is weak and has to run away,so in the game Liu Bei has a skill called "Dunzou". This time you are playing the role of Liu Bei.As Cao Cao's power is so strong, there is nothing you can do but escaping. Please select an optimal path to achieve the purpose .
To simplify the problem, Liu Bei can only move in one of the four direction (up, down,right,left) each time. The map contains the following characters: 
‘A’ : Representative of watchtower, which has an attack range of 2(measured by Manhattan distance),and an attack damage of 1. 
‘B’ : Representative of Fort, which has an attack range of 3(measured by Manhattan distance),and an attack damage of 2. 
‘C’ : Representative of Flame, which has an attack damage of 3 to those who step onto it. 
‘D’ : Representative of Archer, which has anattack range of 2(measured by Manhattan distance), and an attack damage of 4. 
‘E’ : Representative of Ordinary soldier, which has anattack range of 1(measured by Manhattan distance), and an attack damage of 5. 
‘$’ : Representative of Liu Bei. 
‘!’ : Representative of Destination. 
'#' : Representative of obstacles 
‘.’ : Representative of floor. 
Liu Bei can not enter watchtower, forts, Archers, ordinary soldiers,But he can step onto flame or floor. 
Some important rules you should note: 
1.  Liu Bei will not be hurt by the same thing twice.For example,if Liu Bei has been hurt by one watchtower before,then he step into the attack range of some watchtower later,he will not be hurt. 
2.  When Liu Bei reach the destination,you should first judge the attack damage at the destination then finish the game. 
3.  You needn’t judge the attack damage at the start position. 
Please choose a path which LiuBei would cost the least HP. 

Input

In the first line there is an integer T, indicates the number of test cases.(T<=60) 
In each case,the first line of the input contains two integer n,m(1<=n,m<=50),reperesenting the size of map(n*m).Then follow n lines,each line contain m characters. 
There may be some blank lines between each case. 

Output

For each test case , output “Case d: “ where d is the case number counted from one.If Liu Bei can reach the destination then output the minimum HP LiuBei may lose, otherwise output -1.

Sample Input

1
4 3
.$.
ACB
ACB
.!.

Sample Output

Case 1: 6
题意:给一个地图让你找出由 $ 到达 ! 所遭受的最少的伤害
心路历程:首先想到的是找出起始和终止位置进行dfs并对搜索到的点进行曼哈顿距离为1--3的查找并不断更新找到 ! 时的最小结果直到找完并最后输出结果。提交之后发现TLE了,然后就是对此代码进行各种优化还是超时,最后发现学长给出的提示是要用bfs写。然后就大致不变用bfs又写了一次发现错了,还改不了。没办法百度了一下,发现时优先队列,感觉一阵的懵逼啊!!!又在网上找了一个链接学习了一番(http://www.cnblogs.com/heqinghui/archive/2013/07/30/3225407.html),最后使用优先队列和bfs给过了。
思路:用队列顶部储存 $ 的位置和所受的伤害,接着进行bfs不断地更新所受到的伤害知道找到 ! 跳出,打印最后结果即可。
AC代码:
  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include<queue>
  5 #include<vector>
  6 using namespace std;
  7 typedef struct p
  8 {
  9     int x,y,dag;
 10     bool operator <(const p&a) const
 11     {
 12         return dag>a.dag;
 13     }
 14 } point;
 15 int f[24][2]= {{1,0},{-1,0},{0,1},{0,-1},{1,1},{1,-1},{-1,1},{-1,-1},{0,2},{0,-2},{2,0},{-2,0},{2,1},{2,-1},{1,2},{1,-2},{-2,1},{-2,-1},{-1,2},{-1,-2},{3,0},{-3,0},{0,3},{0,-3}};
 16 int d[4][2]= {{1,0},{-1,0},{0,1},{0,-1}};
 17 int flag[55][55][6],dage[55][55][6];
 18 point stare;
 19 int t,n,m;
 20 char s[55][55];
 21 int find(int x,int y)
 22 {
 23     int tx,ty;
 24     if(s[x][y]=='C')
 25         dage[x][y][3]=1;
 26     for(int i=0; i<24; i++)
 27     {
 28         tx=x+f[i][0];
 29         ty=y+f[i][1];
 30         if(tx<0||tx>=n||ty<0||ty>=m)
 31             continue;
 32         if(i<4&&s[tx][ty]=='E')
 33         {
 34             if(s[tx][ty]=='E')
 35                 dage[x][y][5]=1;
 36             if(s[tx][ty]=='A')
 37                 dage[x][y][1]=1;
 38             if(s[tx][ty]=='D')
 39                 dage[x][y][4]=1;
 40             if(s[tx][ty]=='B')
 41                 dage[x][y][2]=1;
 42         }
 43         else if(i<12)
 44         {
 45             if(s[tx][ty]=='B')
 46                 dage[x][y][2]=1;
 47             if(s[tx][ty]=='A')
 48                 dage[x][y][1]=1;
 49             if(s[tx][ty]=='D')
 50                 dage[x][y][4]=1;
 51         }
 52         else if(i<24)
 53         {
 54             if(s[tx][ty]=='B')
 55                 dage[x][y][2]=1;
 56         }
 57     }
 58     return 0;
 59 }
 60 int bfs()
 61 {
 62     priority_queue<point>que;
 63     point cur,next;
 64     int i;
 65     s[stare.x][stare.y]='#';
 66     que.push(stare);
 67     while(!que.empty())
 68     {
 69         cur=que.top();
 70         que.pop();
 71         for(int i=0; i<4; i++)
 72         {
 73             next.x=cur.x+d[i][0];
 74             next.y=cur.y+d[i][1];
 75             if(next.x<0||next.x>=n||next.y<0||next.y>=m)
 76                 continue;
 77                 if(s[next.x][next.y]!='#')
 78             next.dag=cur.dag;
 79             if(s[next.x][next.y]=='!'||s[next.x][next.y]=='.'||s[next.x][next.y]=='C')
 80             {
 81                 find(next.x,next.y);
 82                 for(int t=1; t<6; t++)
 83                 {
 84                     if(dage[next.x][next.y][t]!=0&&flag[cur.x][cur.y][t]==0)
 85                     {
 86                         flag[next.x][next.y][t]++;
 87                         next.dag=next.dag+t;
 88                     }
 89                     if(flag[cur.x][cur.y][t]!=0)
 90                     {
 91                         flag[next.x][next.y][t]=flag[cur.x][cur.y][t];
 92                     }
 93                 }
 94                 if(s[next.x][next.y]!='!')
 95                 s[next.x][next.y]='#';
 96                 que.push(next);
 97             }
 98             if(s[next.x][next.y]=='!')
 99             {
100                 return next.dag;
101             }
102         }
103     }
104     return -1;
105 }
106 int main()
107 {
108     int p;
109     while(~scanf("%d",&p))
110     {
111         for(int k=1; k<=p; k++)
112         {
113             scanf("%d%d",&n,&m);
114             for(int i=0; i<n; i++)
115             {
116                 scanf("%s",s[i]);
117                 for(int j=0; j<m; j++)
118                 {
119                     if(s[i][j]=='$')
120                     {
121                         stare.x=i;
122                         stare.y=j;
123                         stare.dag=0;
124                     }
125                 }
126             }
127             memset(flag,0,sizeof(flag));
128             memset(dage,0,sizeof(dage));
129             printf("Case %d: ",k);
130             printf("%d\n",bfs());
131         }
132     }
133     return 0;
134 }
View Code

心得体会:做题时总会遇到自己不会的或者没有学过的知识,要勇敢地去学习知识!!!

 
posted @ 2016-10-14 20:48  Wally的博客  阅读(183)  评论(0编辑  收藏  举报