2143: 飞飞侠

Dijkstra跑了25S差点以为要炸,回头看了一下发现时限是50S。。。。。。。。

难得在BZOJ上找到这么水的题。

NOIP水平不多说了。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int inf=1e9;
struct Heapnode{
	int x,y,d;
	bool operator<(const Heapnode &rhs)const{
		return d>rhs.d;
	}
};
int d[155][155],A[155][155],B[155][155],n,m;
bool done[155][155];
void dijkstra(int sx,int sy){
	priority_queue<Heapnode>q;
	memset(d,0x3f,sizeof(d));d[sx][sy]=0;
	memset(done,false,sizeof(done));
	q.push((Heapnode){sx,sy,0});
	while(!q.empty()){
		Heapnode tmp=q.top();q.pop();
		int x=tmp.x,y=tmp.y;if(done[x][y])continue;
		done[x][y]=true;
		int l=x-B[x][y],r=x+B[x][y];
		for(int i=1;i<=B[x][y];i++){
			if(y-i<1)break;
			int tmpl=l+i,tmpr=r-i;
			tmpl=max(tmpl,1);tmpr=min(tmpr,m);
			for(int j=tmpl;j<=tmpr;j++)
			if(d[j][y-i]>d[x][y]+A[x][y]){
				d[j][y-i]=d[x][y]+A[x][y];
				q.push((Heapnode){j,y-i,d[j][y-i]});
			}
		}
		for(int i=1;i<=B[x][y];i++){
			if(y+i>m)break;
			int tmpl=l+i,tmpr=r-i;
			tmpl=max(tmpl,1);tmpr=min(tmpr,m);
			for(int j=tmpl;j<=tmpr;j++)
			if(d[j][y+i]>d[x][y]+A[x][y]){
				d[j][y+i]=d[x][y]+A[x][y];
				q.push((Heapnode){j,y+i,d[j][y+i]});
			}
		}
		l=max(l,1);r=min(r,n);
		for(int i=l;i<=r;i++)
		if(d[i][y]>d[x][y]+A[x][y]){
			d[i][y]=d[x][y]+A[x][y];
			q.push((Heapnode){i,y,d[i][y]});
		}
	}
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
	for(int j=1;j<=m;j++)scanf("%d",&B[i][j]);
	for(int i=1;i<=n;i++)
	for(int j=1;j<=m;j++)scanf("%d",&A[i][j]);
	int x[3],y[3],ans[3];
	for(int i=0;i<3;i++)scanf("%d%d",&x[i],&y[i]);
	memset(ans,0,sizeof(ans));
	for(int i=0;i<3;i++){
		dijkstra(x[i],y[i]);
		for(int j=0;j<3;j++)
		ans[j]+=d[x[j]][y[j]];
	}
	int res=1e9,p;
	for(int i=0;i<3;i++)
	if(ans[i]<res)res=ans[i],p=i;
	if(res>=inf){printf("NO");return 0;}
	switch(p){
		case 0:printf("X");break;
		case 1:printf("Y");break;
		case 2:printf("Z");break;
	}
	printf("\n%d",res);
	return 0;
}
		


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值