2012-A3-0013
从 Trac 迁移的文章
这是从旧校内 Wiki 迁移的文章,可能存在一些样式问题,您可以向 memset0 反馈。
原文章内容如下:
题意:一个N×M的格子地图,单位时间可以走一格,有些格不可以走,有些格有每过一个单位时间转向的NPC,在改时刻经过他面向的一定距离的格子会发生一次事件,
指定起点和终点,求一条路径最少发生几次事件,以及此状况下的最短路径长度..
需要注意的几点和背景游戏中不一样的设定,NPC面向的距离不因不可通行的格子而减少,每个NPC不会只触发一次事件(可以触发多次).
所有面向方向以模4为循环,可记录每个地点在模4时间下的触发事件数,然后记忆化BFS,记忆每个地点模4时间下的最小代价,最小代价是双关键字的。
{{{
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
#define go(i,n) for(size_t i=0;i<n;++i)
#define F first
#define S second
const char*d="ESWN";
const int mx[4]={0,1,0,-1},my[4]={1,0,-1,0};
typedef pair<int,int> ii;
const ii operator+(const ii&a,int b){return ii(a.F+b,a.S+1);}
char s[104][128];
ii f[104][104][4];
int p[104][104][4];
int main(){
for(int sx,sy,dx,dy,n,m,w;~scanf("%d%d%d ",&n,&m,&w);){
go(i,n)gets(s[i+1]+1);
go(i,n)go(j,m)memset(f[i+1][j+1],0x1f,32),memset(p[i+1][j+1],0,16);
go(i,w){int x,y,l,k;
scanf("%d%d%d ",&x,&y,&l);
s[x][y]='*';k=strchr(d,getchar())-d;
go(j,4){int a=x,b=y;
go(_,l){a+=mx[k],b+=my[k];
if(!a||!b||a>n||b>m)break;
++p[a][b][j];
}(++k)&=3;
}
}
scanf("%d%d%d%d",&sx,&sy,&dx,&dy);
queue<int> q;
f[sx][sy][0]=ii(p[sx][sy][0],0);
q.push(sx<<16|sy<<2);
for(int k,a,b;q.size();q.pop()){
sx=q.front()>>16;
sy=q.front()>>2&127;
k=q.front()&3;
go(j,4){
a=sx+mx[j];
b=sy+my[j];
if(!a||!b||a>n||b>m||s[a][b]=='*')continue;
ii t =f[sx][sy][k]+p[a][b][k+1&3];
if(t<f[a][b][k+1&3])
f[a][b][k+1&3]=t,q.push(a<<16|b<<2|(k+1&3));
}
}
ii t =min(min(f[dx][dy][0],f[dx][dy][1]),min(f[dx][dy][2],f[dx][dy][3]));
(t.F&0x10000000)?puts("-1"):printf("%d %d\n",t.F,t.S);
}
}
}}}
题意:一个N×M的格子地图,单位时间可以走一格,有些格不可以走,有些格有每过一个单位时间转向的NPC,在改时刻经过他面向的一定距离的格子会发生一次事件,
指定起点和终点,求一条路径最少发生几次事件,以及此状况下的最短路径长度..
需要注意的几点和背景游戏中不一样的设定,NPC面向的距离不因不可通行的格子而减少,每个NPC不会只触发一次事件(可以触发多次).
所有面向方向以模4为循环,可记录每个地点在模4时间下的触发事件数,然后记忆化BFS,记忆每个地点模4时间下的最小代价,最小代价是双关键字的。
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
#define go(i,n) for(size_t i=0;i<n;++i)
#define F first
#define S second
const char*d="ESWN";
const int mx[4]={0,1,0,-1},my[4]={1,0,-1,0};
typedef pair<int,int> ii;
const ii operator+(const ii&a,int b){return ii(a.F+b,a.S+1);}
char s[104][128];
ii f[104][104][4];
int p[104][104][4];
int main(){
for(int sx,sy,dx,dy,n,m,w;~scanf("%d%d%d ",&n,&m,&w);){
go(i,n)gets(s[i+1]+1);
go(i,n)go(j,m)memset(f[i+1][j+1],0x1f,32),memset(p[i+1][j+1],0,16);
go(i,w){int x,y,l,k;
scanf("%d%d%d ",&x,&y,&l);
s[x][y]='*';k=strchr(d,getchar())-d;
go(j,4){int a=x,b=y;
go(_,l){a+=mx[k],b+=my[k];
if(!a||!b||a>n||b>m)break;
++p[a][b][j];
}(++k)&=3;
}
}
scanf("%d%d%d%d",&sx,&sy,&dx,&dy);
queue<int> q;
f[sx][sy][0]=ii(p[sx][sy][0],0);
q.push(sx<<16|sy<<2);
for(int k,a,b;q.size();q.pop()){
sx=q.front()>>16;
sy=q.front()>>2&127;
k=q.front()&3;
go(j,4){
a=sx+mx[j];
b=sy+my[j];
if(!a||!b||a>n||b>m||s[a][b]=='*')continue;
ii t =f[sx][sy][k]+p[a][b][k+1&3];
if(t<f[a][b][k+1&3])
f[a][b][k+1&3]=t,q.push(a<<16|b<<2|(k+1&3));
}
}
ii t =min(min(f[dx][dy][0],f[dx][dy][1]),min(f[dx][dy][2],f[dx][dy][3]));
(t.F&0x10000000)?puts("-1"):printf("%d %d\n",t.F,t.S);
}
}