本文主要是介绍HDU 3442 Three Kingdoms 优先队列(非状压做法),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
题意:给出一个maze(某三国志类型游戏地图)
$ 代表起点
!代表终点
. 代表路
# 代表墙
A,B,C,D,E分别代表不同的防御塔,其射程和攻击力各不相同。但其中只有C是可以走的。且每种防御塔只会造成一次伤害。
求最小伤害,到不了终点惯例输出-1
思路:先用bfs把地图染色,记住每个点都会收到什么伤害,这里用set实现。
再bfs寻路,每个点的所有状态用点集表示(set<set<int> >,set<int>是点集,就是一种状态,而set<set<int> >就是一点的状态集),在bfs时确定同一个点不会有重复的状态被压入队列。
又考虑到状态较多,可能会MLE,使用优先队列,略去多余的状态点。
非状压做法代码:
<span style="font-size:14px;">#include <iostream>
#include <queue>
#include <cstring>
#include <cstdio>
#include <set>
#include <map>
#include <algorithm>
#include <stack>
using namespace std;
bool vis[60][60];
set <int> maze[60][60];
int dirx[]={0,-1,1,0};
int diry[]={-1,0,0,1};
set <int> em;
typedef struct Node{int x;int y;int sum;public:Node(int xx,int yy,int ss){x=xx;y=yy;sum=ss;}
}Node;
typedef struct node{int x;int y;set <int> s;int ans;bool operator < (const node &a)const{if(a.ans==ans){if(a.x==x)return a.y<y;return a.x<x;}return a.ans<ans;}public:node(int xx,int yy,set<int> ss,int a){x=xx;y=yy;s=ss;a=0;set<int>::iterator it;for(it=s.begin();it!=s.end();it++)a+=*it;ans=a;}
}node;
const int INF=0x3f3f3f3f;
int n,m,stx,sty,enx,eny;
void bfs(int x,int y,int r,int d){//。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。bfs对图染色queue <Node> que;que.push(Node(x,y,r));bool tvis[60][60]={0};tvis[x][y]=1;while(!que.empty()){Node t=que.front();que.pop();if(t.sum<0)continue;else{maze[t.x][t.y].insert(d);//。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。一点上的初始状态(会被哪些塔攻击到)for(int i=0;i<4;i++){int xx=dirx[i]+t.x;int yy=diry[i]+t.y;if(tvis[xx][yy]||xx<0||xx>=n||yy<0||yy>=m)continue;que.push(Node(xx,yy,t.sum-1));tvis[xx][yy]=0;}}}return ;
}
int main()
{int T;scanf("%d",&T);getchar();em.clear();for(int ppp=1;ppp<=T;ppp++){scanf("%d %d",&n,&m);getchar();memset(vis,0,sizeof(vis));for(int i=0;i<60;i++)for(int j=0;j<60;j++)maze[i][j].clear();char x;int ans=INF;enx=INF;eny=INF;for(int i=0;i<n;i++){for(int j=0;j<m;j++){scanf("%c",&x);if(x=='A'){bfs(i,j,2,1);vis[i][j]=1;}else if(x=='B'){bfs(i,j,3,2);vis[i][j]=1;}else if(x=='C'){bfs(i,j,0,3);}else if(x=='D'){bfs(i,j,2,4);vis[i][j]=1;}else if(x=='E'){bfs(i,j,1,5);vis[i][j]=1;}else if(x=='$'){stx=i;sty=j;}else if(x=='!'){enx=i;eny=j;}else if(x=='#'){vis[i][j]=1;}}getchar();}priority_queue <node> que;que.push(node(stx,sty,em,0));set <set<int> > event[60][60];//。。。。。。。。。。。。。。。。。。。。。。。。。。。。地图上每点的状态集初始为空for(int i=0;i<n;i++){for(int j=0;j<m;j++){event[i][j].clear();}}event[stx][sty].insert(em);while(!que.empty()){node t=que.top();que.pop();if(t.x==enx&&t.y==eny){ans=t.ans;break;}else{for(int i=0;i<4;i++){int xx=dirx[i]+t.x;int yy=diry[i]+t.y;if(xx<0||yy<0||xx>=n||yy>=m||vis[xx][yy]) continue;set <int> mix;set_union(t.s.begin(),t.s.end(),maze[xx][yy].begin(),maze[xx][yy].end(),inserter(mix,mix.begin()));if(event[xx][yy].find(mix)==event[xx][yy].end()){//。。。。。。。。。。。。。。。若新的状态在点上没有出现过,就入队que.push(node(xx,yy,mix,0));event[xx][yy].insert(mix);//。。。。。。。。。。。。。。。。。。。。。。。。更新点的状态集}}}}if(ans==INF)ans=-1;printf("Case %d: %d\n",ppp,ans);}
}</span><span style="font-size:24px;">
</span>
Description
‘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 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
Sample Input
1 4 3 .$. ACB ACB .!.
Sample Output
Case 1: 6
这篇关于HDU 3442 Three Kingdoms 优先队列(非状压做法)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!