《ybtoj高效进阶》第一部分第五章例题4 荆轲刺秦王&P6474

题目大意

给n*m的矩阵,要从S到T,途中有卫兵,其观察范围为曼哈顿距离<=xi,j(即该卫兵的视力),现在有2种技能,无使用冷却,有次数限制:

  1. 隐形,不被卫兵发现
  2. 瞬移,从普通转移的8联通变成4联通,距离为d,普通和瞬移用时均为1

求从S到T的最短用时,在用时最短的情况下,要求技能总次数最少,如果还有多种情况,要求隐形次数最少。

思路

首先,对于一个卫兵的观察范围,我们需要差分处理(TLE警告),因此,数组最少要开352(RE警告)。
然后,在bfs时,我们需要剪枝(TLE警告)如下:

  1. 如果现在的用时已经>之前的最优值时,break;
  2. 如果该点隐形x次,瞬移y次的情况已经有了,那么我们不需要处理ta,直接跳过

最后,我们需要考虑输出-1的情况。(WA警告)
code:

#include<iostream>
#include<cmath>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
string x;
int a[361][361],sx,sy,ex,ey,n,m,cq,cm,d;
bool b[361][361];
int c[361][361][16][16]; 
int q[12][3]={
    
    {
    
    0,1,0},{
    
    1,0,0},{
    
    -1,0,0},{
    
    0,-1,0},{
    
    -1,-1,0},{
    
    1,1,0},{
    
    1,-1,0},{
    
    -1,1,0},{
    
    0,0,1},{
    
    0,0,1},{
    
    0,0,1},{
    
    0,0,1}};
struct f{
    
    
	int x,y,w,j,b;
} o,op;
queue<f> p;
int mn=0x7f7f7f7f,mnx,mny;
void bfs()
{
    
    
	while (p.size())
	{
    
    
		o=p.front();
		p.pop();
		op.b=o.b+1;
		if (op.b>mn) continue;
		for (int i=0;i<=11;i++)
		{
    
    
			op.x=o.x+q[i][0],op.y=o.y+q[i][1],op.j=o.j+q[i][2];
			if (op.x<1||op.x>n||op.y<1||op.y>m||op.j>cm||b[op.x][op.y]==1) continue;
			op.w=o.w+(a[op.x][op.y]>0?1:0);
			if (op.w>cq||c[op.x][op.y][op.w][op.j]) continue;
			if (op.x==ex&&op.y==ey)
			{
    
    
				if (mn>op.b||(mn==op.b&&mnx+mny>op.w+op.j)||(mn==op.b&&mnx+mny==op.w+op.j&&mnx>op.w))
				{
    
    
					mn=op.b;
					mnx=op.w;
					mny=op.j;
				}
			}
			c[op.x][op.y][op.w][op.j]=1;
			p.push(op);
		}
	}
	if (mn==0x7f7f7f7f) cout<<-1;
	else cout<<mn<<' '<<mnx<<' '<<mny<<endl;
	return;
}
int main()
{
    
    
	cin>>n>>m>>cq>>cm>>d;
	q[11][1]=d,q[10][1]=-d,q[9][0]=d,q[8][0]=-d;
	for (int i=1;i<=n;i++)
	{
    
    
		for (int j=1;j<=m;j++)
		{
    
    
			cin>>x;
			if (x=="S")
			{
    
    
				sx=i,sy=j;
				continue;
			}
			if (x=="T")
			{
    
    
				ex=i,ey=j;
				continue;
			}
			if (x==".") continue;
			int u=0;
			for (int k=0;k<x.size();k++) u=u*10+x[k]-'0';
			b[i][j]=1;
			for (int ii=max(1,i-u+1);ii<=min(n,i+u-1);ii++)
			{
    
    
				int uu=min(m,j+u-1-abs(i-ii));
				int jj=max(1,j-u+1+abs(i-ii));
				a[ii][uu+1]--,a[ii][jj]++;
			}
		}
	}
	for (int i=1;i<=n;i++) for (int j=1;j<=m;j++)
	{
    
    
		a[i][j]+=a[i][j-1];
	}
	o.x=sx,o.y=sy;
	c[sx][sy][0][0]=1;
	p.push(o);
	bfs();
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_49843717/article/details/112393688
今日推荐