题目意思:给你一个n*m的迷宫,+能走,*障碍物,一个胖子一开始在3,3,体积为5*5
不过胖子走迷宫的目的是为了减肥,给你一个时间k,当到达时间k时,胖子饿瘦了变成3*3,当到达时间2*k时,更瘦了变成1*1
题目要求到达(n-2,m-2)这个点所需的最短时间。
n,m<=300,
解决思路,参考hdu1026,bfs+优先队列(这里如果 不直接原地跳跃到k时刻,而是选择time+1呆在原地,那么不用优先队列也可以,优先队列的作用是,每一层扩展开来的结点是会改变时刻的,比如说hdu1026是要在一个节点打怪打几个小时,而普通的队列bfs,以其扩展顺序为时刻,所以按顺序搜索就行了)
注意几点:
1.四个方向的写法:int foot[4][2]={-1,0,1,0,0,-1,0,1};
2.根据当前时间判断胖子大小,然后决定胖子在原地待多少时间(k或者2k)
3.学会了freopen重定向的写法
4.迷宫问题还是在周围附一圈边界写起来方便
5.pre数组主要是为了记录路径方便查看(来自hdu1026),print1函数也是为了打印路径,可忽略。
6.可以尝试que.push({ nex.ti,nex.x,nex.y,nex.da});(与定义int ti,x,y,da;顺序相对应) 的写法
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<bitset>
#include<cmath>
#include<set>
#include<list>
#include<deque>
#include<map>
#include<queue>
using namespace std;
char a[310][310];
bool p[310][310];
int n,m,k,dada,num;
int foot[4][2]={-1,0,1,0,0,-1,0,1};
struct node
{
int ti,x,y,da;
friend bool operator < (node a,node b)
{
return (a.ti>b.ti) || ((a.ti==b.ti)&&(a.da>b.da));
}
};
priority_queue<node>q;
struct route
{
int x,y,da,ti;
}pre[310][310][6];
bool pan(int x,int y,int da)
{
for (int i=x-da;i<=x+da;i++)
for (int j=y-da;j<=y+da;j++)
if (a[i][j]=='*') return false;
return true;
}
int bfs()
{
node w;
w.x=3;w.y=3;w.ti=0;w.da=5;
q.push(w);
w.x=3;w.y=3;w.ti=k;w.da=3;
q.push(w);
w.x=3;w.y=3;w.ti=2*k;w.da=1;
q.push(w);
pre[3][3][5].x=-1;pre[3][3][5].y=-1;
pre[3][3][3].x=-1;pre[3][3][3].y=-1;
pre[3][3][1].x=-1;pre[3][3][1].y=-1;
p[3][3]=1;
w=q.top();
while (w.x!=n-2 || w.y!=m-2)
{
node nex,tem;
for (int i=0;i<4;i++)
{
int x=w.x+foot[i][0],y=w.y+foot[i][1];
if (pan(x,y,w.da/2) && p[x][y]==0)
{
p[x][y]=1;
nex.x=x;nex.y=y;nex.ti=w.ti+1;
if (nex.ti>=2*k) nex.da=1;
else if (nex.ti>=k)
{
nex.da=3;
tem.x=x;tem.y=y;tem.ti=2*k;tem.da=1;
q.push(tem);
pre[tem.x][tem.y][tem.da].x=nex.x;
pre[tem.x][tem.y][tem.da].y=nex.y;
pre[tem.x][tem.y][tem.da].da=nex.da;
pre[tem.x][tem.y][tem.da].ti=nex.ti;
}
else
{
nex.da=5;
tem.x=x;tem.y=y;tem.ti=2*k;tem.da=1;
pre[tem.x][tem.y][tem.da].x=nex.x;
pre[tem.x][tem.y][tem.da].y=nex.y;
pre[tem.x][tem.y][tem.da].da=nex.da;
pre[tem.x][tem.y][tem.da].ti=nex.ti;
q.push(tem);
tem.x=x;tem.y=y;tem.ti=k;tem.da=3;
pre[tem.x][tem.y][tem.da].x=nex.x;
pre[tem.x][tem.y][tem.da].y=nex.y;
pre[tem.x][tem.y][tem.da].da=nex.da;
pre[tem.x][tem.y][tem.da].ti=nex.ti;
q.push(tem);
}
q.push(nex);
pre[nex.x][nex.y][nex.da].x=w.x;
pre[nex.x][nex.y][nex.da].y=w.y;
pre[nex.x][nex.y][nex.da].da=w.da;
pre[nex.x][nex.y][nex.da].ti=w.ti;
}
}
q.pop();
if (q.empty()) break;
w=q.top();
}
dada=w.da;
if (!q.empty()) return w.ti;
else return 0;
}
void print1(int n,int m,int dad,int tt)
{
int x=pre[n][m][dad].x,y=pre[n][m][dad].y,da=pre[n][m][dad].da,ti=pre[n][m][dad].ti;
if (x<0) return;
print1(x,y,da,ti);
num++;
printf("%ds:(%d,%d)->(%d,%d),da=%d\n",tt,x,y,n,m,dad);
/*int z=0;
if (a[n][m]!='.') z=a[n][m]-'0';
for (int i=1;i<=z;i++)
{
num++;
printf("%ds:FIGHT AT (%d,%d)\n",num,n-1,m-1);
}*/
}
int main()
{
freopen("f1_input.txt","r",stdin); //输入重定向,输入数据将从in.txt文件中读取
freopen("f1_output.txt","w",stdout); //输出重定向,输出数据将保存在out.txt文件中
scanf("%d%d%d",&n,&m,&k);getchar();
for (int i=1;i<=n;i++)
{
for (int j=1;j<=m;j++)
{
a[i][j]=getchar();
}getchar();
}
for (int i=0;i<4;i++)
{
printf("%d %d\n",foot[i][0],foot[i][1]);
}
//return 0;
printf("%d %d\n",n,m);
for (int i=1;i<=n;i++)
{
for (int j=1;j<=m;j++)
{
printf("%c",a[i][j]);
}printf("\n");
}
for (int i=1;i<=n;i++)
{
a[i][0]='*';
a[i][m+1]='*';
}
for (int j=1;j<=m;j++)
{
a[0][j]='*';
a[n+1][j]='*';
}
while (!q.empty()) q.pop();
memset(p,0,sizeof(p));
memset(pre,0,sizeof(pre));
int ans=bfs();
printf("%d\n",ans);
num=0;
/*for (int i=1;i<=n;i++)
{
for (int j=1;j<=m;j++)
{
for (int k=1;k<=5;k=k+2)
printf("%d %d %d\n",pre[i][j][k].x,pre[i][j][k].y,pre[i][j][k].da);
printf("j=%d\n",j);
}printf("\n");
}*/
print1(n-2,m-2,dada,ans);
fclose(stdin);//关闭文件
fclose(stdout);//关闭文件
return 0;
}
结果:
参考博客: