2143: 飞飞侠

我是真的菜...

一开始写了一个裸的bfs ,理所当然的tle了,

考虑如何优化...

考虑对于一个点(i,j)能跳b[i][j]次的含义,就是对于他先花费a[i][j]跳到周围其他某个点上,并且以后还能0花费到达另一个周围的电上,但是总共只能跳b[i][j]次..

考虑一个点拆成300个点,那么他能跳b[i][j],相当于我从当前层(i,j,0)花费了a[i][j]跳到了目标层(i,j,b[i][j]),

然后接下来我能花费为0跳到(i±1,j±1,b[i][j] - 1)这层,然后显而易见从上面的层到下面的层花费均为0.

那么就可以大量优化边数...注意对于考虑点x时,如果他的值已经比三人所在点花费大,直接略过...没加这个优化卡了我一晚上...

c++代码如下:

#include<bits/stdc++.h>
#define lowbit(x) (x & -x)
#define rep(i,x,y) for(register int i = x ;i <= y; ++ i)
#define repd(i,x,y) for(register int i = x ; i >= y ; --i)
typedef long long ll;
template<typename T>inline void read(T&x)
{
	x = 0;char c;int sign = 1;
	do { c = getchar();if(c == '-') sign = -1; }while(!isdigit(c));
	do { x = x * 10 + c - '0'; c = getchar(); }while(isdigit(c));
	x *= sign;
}
using namespace std;
const int N = 151,M = 302;
int a[N][N],b[N][N],d[N][N][M],dis[3][3],cnt,ans,idx,n,m;
struct Point { int x,y; }p[3];
struct Str
{
	int x,y,z,w;
	Str(int x = 0, int y = 0, int z = 0,int w = 0) : x(x), y(y), z(z),w(w) {}
};
int X[4] = {1,-1,0,0};
int Y[4] = {0,0,1,-1};
priority_queue<Str> q;

bool operator < (const Str a,const Str b) { return a.w > b.w; }

void Spfa(int T)
{
	rep(i,1,n) rep(j,1,m) rep(k,0,n+m) d[i][j][k] = 1e9;
	d[p[T].x][p[T].y][0] = 0;
	q.push((Str){p[T].x,p[T].y,0,0});
	while(!q.empty())
	{
		Str x = q.top();q.pop();
		
		bool e = 1;
		rep(i,0,2) if(d[p[i].x][p[i].y][0] > x.w) e = 0;
		if(e) continue;
		
		if(x.z)
		{
			rep(i,0,3)
			{
				int xx = x.x + X[i],yy= x.y + Y[i];
				if(!xx || !yy || xx > n || yy > m) continue;
				if(d[xx][yy][x.z - 1] > d[x.x][x.y][x.z]) {
					d[xx][yy][x.z - 1] = d[x.x][x.y][x.z];
					q.push((Str){xx,yy,x.z - 1,d[xx][yy][x.z - 1]});
				}
			}
			
			if(d[x.x][x.y][x.z - 1] > d[x.x][x.y][x.z]){
				d[x.x][x.y][x.z - 1] = d[x.x][x.y][x.z];
				q.push((Str){x.x,x.y,x.z - 1,d[x.x][x.y][x.z - 1]});
			}
		}
		else if(b[x.x][x.y])
		{
			int mx = min(n+m,b[x.x][x.y]);
			if(d[x.x][x.y][mx] > d[x.x][x.y][x.z] + a[x.x][x.y]){
				d[x.x][x.y][mx] = d[x.x][x.y][x.z] + a[x.x][x.y];
				q.push((Str){x.x,x.y,mx,d[x.x][x.y][mx]});
			}
		}
	}
}

int main()
{
	ans = 1e9;
	read(n); read(m);
	rep(i,1,n) rep(j,1,m) read(b[i][j]);
	rep(i,1,n) rep(j,1,m) read(a[i][j]);
	rep(i,0,2) read(p[i].x),read(p[i].y);
	
	rep(j,0,2)
	{
		Spfa(j);
		rep(i,0,2)
			dis[j][i] = d[p[i].x][p[i].y][0];
	}
	
	rep(i,0,2)
	{
		cnt = 0;
		rep(j,0,2) cnt += dis[j][i];
		if(cnt < ans)
		{
			ans = cnt;
			idx = i;
		}
	}
	
	if(ans == 1e9) puts("NO");
	else printf("%c\n%d\n",idx == 0?'X' : idx == 1 ?'Y':'Z',ans);
	
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值