荆轲刺秦王
题目描述
输入格式
第一行五个整数
n
,
m
,
c
1
,
c
2
,
d
n,m,c_1,c_2,d
n,m,c1,c2,d,代表地图的大小为n*m隐身的使用限制次数为
c
1
c_1
c1,瞬移的使用次数为
c
2
c_2
c2,和一次瞬移的距离d。
接下来n行,每行m个元素。每个字符为“S”或“T”或“.”或一个正整数
a
i
,
j
a_i,_j
ai,j代表一个格点,具体含义详见题目描述。
输出格式
若荆轲无法到达秦王所在点,则输出一行一个 -1。
否则输出一行三个整数
t
,
u
1
,
u
2
t,u_1,u_2
t,u1,u2,依次代表所需的最短时间,隐身的使用次数与瞬移的使用次数。
样例输入
输入样例1
5 4 0 0 5
. 1 T 1
. . . 2
. 1 . .
S . . .
1 . . .
输出样例1
3 0 0
输入样例2
8 6 2 3 3
. S . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
2 . 2 . 2 .
. . 1 . T .
3 . 1 . . 3
输出样例2
3 1 3
解题思路
如果没有技能的使用次数限制,这道题就是个广搜,但这道题加上了次数限制,就不能用(x,y)来描述荆轲的状态了。
这道题还有一个难点就是卫兵观察位置的预处理
#include<cmath>
#include<cstdio>
#include<iostream>
using namespace std;
int n,m,c1,c2,d,ex,ey,answer1=100000,answer2=100000,answer3=100000,answer4=100000,b[400][400],z[400][400],c[400][400][20][20];
int dx[8]= {-1,0,1,0,-1,1,1,-1};
int dy[8]= {0,1,0,-1,1,1,-1,-1};
string s;
struct node {
int x,y,c1,c2,ans;
} p[10000005];
void fz(int ans,int c1,int c2) {
answer1=ans;
answer2=c1;
answer3=c2;
answer4=c1+c2;
}
bool check(int x,int y) {
return x>=1&&x<=n&&y>=1&&y<=m;
}
void bfs() {
int head=0,tail=1;
while(head<tail) {
head++;
head%=10000000;
int ox=p[head].x,oy=p[head].y,o1=p[head].c1,o2=p[head].c2,oans=p[head].ans;
for(int i=0; i<8; i++) {
int xx=ox+dx[i],yy=oy+dy[i];
if(check(xx,yy)&&!z[xx][yy]) {
if(b[xx][yy]) {
if(o1+1<=c1&&!c[xx][yy][o1+1][o2]) {
c[xx][yy][o1+1][o2]=1;
p[++tail]=(node) {
xx,yy,o1+1,o2,oans+1
};
tail%=100000000;
if(xx==ex&&yy==ey) {
if(oans+1<answer1)fz(oans+1,o1+1,o2);
else if(oans+1==answer1&&o1+1+o2<answer4)fz(oans+1,o1+1,o2);
else if(oans+1==answer1&&o1+1+o2==answer4&&o1+1<answer2)fz(oans+1,o1+1,o2);
}
}
} else {
if(!c[xx][yy][o1][o2]) {
c[xx][yy][o1][o2]=1;
p[++tail]=(node) {
xx,yy,o1,o2,oans+1
};
tail%=100000000;
if(xx==ex&&yy==ey) {
if(oans+1<answer1)fz(oans+1,o1,o2);
else if(oans+1==answer1&&o1+o2<answer4)fz(oans+1,o1,o2);
else if(oans+1==answer1&&o1+o2==answer4&&o1<answer2)fz(oans+1,o1,o2);
}
}
}
}
if(o2+1<=c2&&i<4) {
int xx=ox+dx[i]*d,yy=oy+dy[i]*d;
if(check(xx,yy)&&!z[xx][yy]) {
if(b[xx][yy]) {
if(o1+1<=c1&&!c[xx][yy][o1+1][o2+1]) {
c[xx][yy][o1+1][o2+1]=1;
p[++tail]=(node) {
xx,yy,o1+1,o2+1,oans+1
};
tail%=100000000;
if(xx==ex&&yy==ey) {
if(oans+1<answer1)fz(oans+1,o1+1,o2+1);
else if(oans+1==answer1&&o1+1+o2+1<answer4)fz(oans+1,o1+1,o2+1);
else if(oans+1==answer1&&o1+1+o2+1==answer4&&o1+1<answer2)fz(oans+1,o1+1,o2+1);
}
}
} else {
if(!c[xx][yy][o1][o2]) {
c[xx][yy][o1][o2+1]=1;
p[++tail]=(node) {
xx,yy,o1,o2+1,oans+1
};
tail%=100000000;
if(xx==ex&&yy==ey) {
if(oans+1<answer1)fz(oans+1,o1,o2+1);
else if(oans+1==answer1&&o1+o2+1<answer4)fz(oans+1,o1,o2+1);
else if(oans+1==answer1&&o1+o2+1==answer4&&o1<answer2)fz(oans+1,o1,o2+1);
}
}
}
}
}
}
}
return;
}
int main() {
scanf("%d%d%d%d%d",&n,&m,&c1,&c2,&d);
for(int i=1; i<=n; i++)
for(int j=1; j<=m; j++) {
cin>>s;
if(s[0]=='S')p[1]=(node) {i,j,0,0},c[i][j][0][0]=1;
else if(s[0]=='T')ex=i,ey=j;
else if(s[0]!='.') {
int len=s.size(),sum=0;
z[i][j]=1;
for(int k=0; k<len; k++)
sum=sum*10+s[k]-48;
for(int x=max(1,i-sum); x<=min(n,i+sum); x++)
for(int y=max(1,j-sum); y<=min(m,j+sum); y++)
if(abs(i-x)+abs(j-y)<sum)
b[x][y]=1;
}
}
bfs();
if(answer1==100000)printf("-1");
else printf("%d %d %d",answer1,answer2,answer3);
return 0;
}