hdu1242
题意:给一个字符地图,a代表要救的人,r代表起点,x代表士兵,.代表道路,走一次花一单位的时间,杀死一个士兵花一单位的时间。求出最少的时间,不能救到就输出Poor ANGEL has to stay in the prison all his life.
经典bfs,用优先队列,按照时间从小到大排序,小的优先级高
不知道为啥,用flag标记的就ac,直接在bfs结束时输出Poor ANGEL has to stay in the prison all his life.就wa
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<set>
#include<queue>
#include<map>
using namespace std;
char mp[205][205];
int m,n;
bool vis[205][205];
int dr[4][2]={1,0,-1,0,0,1,0,-1},flag;
struct node
{
int x,y,cost;
friend bool operator < (const node &a,const node &b)
{
return a.cost>b.cost;
}
};//定义结构体排序
void bfs(int x,int y)
{
node start;
start.x=x;start.y=y;
start.cost=0;
priority_queue <node> q;
q.push(start);
while(!q.empty())
{
node now,nt;
now=q.top();
q.pop();
if(mp[now.x][now.y]=='r')
{
printf("%d\n",now.cost);
flag=0;
break;
}
int nx,ny;
for(int i=0;i<4;i++)
{
nx=dr[i][0]+now.x;
ny=dr[i][1]+now.y;
if(nx>=0&&nx<n&&ny>=0&&ny<m&&!vis[nx][ny]&&mp[nx][ny]!='#')
{
nt.x=nx;nt.y=ny;
if(mp[nx][ny]=='.'||mp[nx][ny]=='r')
{
nt.cost=now.cost+1;
q.push(nt);
vis[nx][ny]=1;
}
else if(mp[nx][ny]=='x')
{
nt.cost=now.cost+2;
q.push(nt);
vis[nx][ny]=1;
}
}
}
}
//如果在这里输出搜不到的情况就是wa,这实在不懂
}
int main()
{
int i,j,ans;
while(scanf("%d%d",&n,&m)==2)
{
memset(vis,0,sizeof(vis));
flag=1;
for(i=0;i<n;i++)
cin>>mp[i];
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
{
if(mp[i][j]=='a')//从a开始,因为有多个r,虽然从r开始也能过
//但是这不能过第三个样例,这是个hdu的bug
{
vis[i][j]=1;
bfs(i,j);
}
}
}
if(flag)printf("Poor ANGEL has to stay in the prison all his life.\n");
}//要用flag标记
return 0;
}
题意:
鸣人要去救被大蛇丸带走的佐助,*代表路,@是鸣人,+是佐助,#代表大蛇丸手下,鸣人有查克拉,1个查克拉可以弄死一个大蛇丸手下(不花时间),走一单位路花一单位时间,如果没有查克拉了,就不能走到有大蛇丸手下的地方。求最少要多少时间才能救出佐助,救不出就输出-1
本着对火影的热爱,想着bfs搜一遍就好,但是一直wa,我非常肯定我bfs已经没有bug了,可是又想不到哪里错了,开始的时候我直接写的普通bfs迷宫,如果走到了#,判断查克拉还有没有,如果有就把查克拉减一,再入队,如果没有就不能走,不入队。
这样写看起来没有问题,我想了很久也没有发现哪里错了。错的地方就在于查克拉,因为走到一个位置,位置和步数(这个状态)是没有问题的,问题在于怎么到这一步的,有可能有很多路都能到这一点,但是有一些路消耗的查克拉少,有的消耗得多,
那么如果选了消耗得多的路,(而且到了这个点,这个点就被标记了不能再走,那么就没有把其他消耗查克拉少的路加入队列)
就很可能救不了佐助。
其实没有什么特别的地方,但是在选择的时候,肯定先选步数少的,如果步数一样,要先选择查克拉多的,用优先队列对结构体进行排序就好
#include<iostream>
#include<string>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<queue>
#include<algorithm>
using namespace std;
typedef long long ll;
struct pos
{
int x,y,t,step;//x,y代表位置,t剩余查克拉
bool operator<(const pos temp)const
{
if(step==temp.step)return t<temp.t;
//在步数相同的时候,先选查克拉多的
return step>temp.step;
//优先选择步数少的
}
};
char mp[205][205];
bool vis[205][205];
int m,n,flag,T,ans;
int dr[4][2]={1,0,-1,0,0,1,0,-1};
void bfs(int x,int y)//bfs模板,毫无技巧可言
{
pos st;
priority_queue<pos>q;
st.x=x;st.y=y;
st.step=0;st.t=T;
q.push(st);
vis[x][y]=1;
while(!q.empty())
{
pos now=q.top();
q.pop();
if(mp[now.x][now.y]=='+')
{
flag=1;
ans=now.step;
break;
}
for(int i=0;i<4;i++)
{
int nx,ny;
nx=now.x+dr[i][0];
ny=now.y+dr[i][1];
if(nx>=0&&nx<n&&ny>=0&&ny<m&&!vis[nx][ny])
{
pos Next;
Next.x=nx;Next.y=ny;
Next.step=now.step+1;
if(mp[nx][ny]=='#')
{
if(now.t>0)
{
Next.t=now.t-1;
q.push(Next);
vis[nx][ny]=1;
}//当走到#,又没有查克拉的时候,不能走
}
else if(mp[nx][ny]!='#')
{
Next.t=now.t;
q.push(Next);
vis[nx][ny]=1;
}
}
}
}
}
int main()
{
int i,j;
while(scanf("%d%d%d",&n,&m,&T)==3)
{
for(i=0;i<n;i++)
scanf("%s",mp[i]);
memset(vis,0,sizeof(vis));
flag=0;
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
{
if(mp[i][j]=='@')
{
bfs(i,j);
break;
}
}
}
if(flag)printf("%d\n",ans);
else printf("-1\n");
}
return 0;
}