【BZOJ2143】飞飞侠
2143: 飞飞侠
Time Limit: 50 Sec Memory Limit: 259 MBSubmit: 794 Solved: 275
[Submit][Status][Discuss]
Description
飞飞国是一个传说中的国度,国家的居民叫做飞飞侠。飞飞国是一个N×M的矩形方阵,每个格子代表一个街区。然而飞飞国是没有交通工具的。飞飞侠完全靠地面的弹射装置来移动。每个街区都装有弹射装置。使用弹射装置是需要支付一定费用的。而且每个弹射装置都有自己的弹射能力。我们设第i行第j列的弹射装置有Aij的费用和Bij的弹射能力。并规定有相邻边的格子间距离是1。那么,任何飞飞侠都只需要在(i,j)支付Aij的费用就可以任意选择弹到距离不超过Bij的位置了。如下图 (从红色街区交费以后可以跳到周围的任意蓝色街区。) 现在的问题很简单。有三个飞飞侠,分别叫做X,Y,Z。现在它们决定聚在一起玩,于是想往其中一人的位置集合。告诉你3个飞飞侠的坐标,求往哪里集合大家需要花的费用总和最低。
Input
输入的第一行包含两个整数N和M,分别表示行数和列数。接下来是2个N×M的自然数矩阵,为Aij和Bij 最后一行六个数,分别代表X,Y,Z所在地的行号和列号。
Output
第一行输出一个字符X、Y或者Z。表示最优集合地点。第二行输出一个整数,表示最小费用。如果无法集合,只输出一行NO
Sample Input
4 4
0 0 0 0
1 2 2 0
0 2 2 1
0 0 0 0
5 5 5 5
5 5 5 5
5 5 5 5
5 5 5 5
2 1 3 4 2 2
0 0 0 0
1 2 2 0
0 2 2 1
0 0 0 0
5 5 5 5
5 5 5 5
5 5 5 5
5 5 5 5
2 1 3 4 2 2
Sample Output
Z
15
【范围】
100% 1 < = N, M < = 150; 0 < = Aij < = 10^9; 0 < = Bij < = 1000
15
【范围】
100% 1 < = N, M < = 150; 0 < = Aij < = 10^9; 0 < = Bij < = 1000
题解:
垃圾题目毁我人生颓我青春
在湖南我有两天都在写这个垃圾题
首先我们发现某个弹射装置就是多条边,这样我们可以转化为求平面图上最短路
但是会T,因为边数过多,所以我们要用点来疏松边
具体怎么做呢?我们再加一维,表示当前高度
dis[i][j][k]表示现在在ij,高度为k的最短路
这样转化之后就可以不用边了
这样复杂度很玄学 但是能过
就这样 我来贴一波代码
View Code
#include<cstdio> #include<cstdlib> #include<iostream> #include<cstring> #include<algorithm> #include<queue> #include<iomanip> #include<stack> #include<map> #include<set> #include<cmath> #define debug(x) cerr<<#x<<"="<<x<<endl #define INF 0x7f7f7f7f #define llINF 0x7ffffffffffll using namespace std; typedef pair<int,int> pii; typedef long long ll; inline int init() { int now=0,ju=1;char c;bool flag=false; while(1) { c=getchar(); if(ju=='-')ju=-1; else if(c>='0'&&c<='9') { now=now*10+c-'0'; flag=true; } else if(flag)return now*ju; } } ll dis[151][151][1005]; int n,m; ll ans=llINF; bool vis[151][151][1005]; int A[151][151]; int B[151][151]; struct node { int x,y,z; ll dis; }; bool operator < (node a,node b) { if(a.dis!=b.dis) { return a.dis>b.dis; } } int topt; char where; #ifdef unix #define LLD "%lld" #else #define LLD "%I64d" #endif int xx,xy,yx,yy,zx,zy; priority_queue<node> q; int dx[5]={1,-1,0,0,0}; int dy[5]={0,0,1,-1,0}; void dijkstra(int x,int y) { node now; for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { for(int k=0;k<=topt;k++) { dis[i][j][k]=llINF; vis[i][j][k]=false; } } } dis[x][y][0]=0; now.x=x;now.y=y;now.z=0;now.dis=0; q.push(now); while(!q.empty()) { now=q.top();q.pop(); if(vis[now.x][now.y][now.z])continue; if(vis[xx][xy][0]+vis[yx][yy][0]+vis[zx][zy][0]==3)break; vis[now.x][now.y][now.z]=1; if(now.z>0) { for(int i=0;i<5;i++) { if(!vis[now.x+dx[i]][now.y+dy[i]][now.z-1]&&now.x+dx[i]>=1&&now.x+dx[i]<=n&&now.y+dy[i]>=1&&now.y+dy[i]<=m) { if(dis[now.x+dx[i]][now.y+dy[i]][now.z-1]>dis[now.x][now.y][now.z]) { dis[now.x+dx[i]][now.y+dy[i]][now.z-1]=dis[now.x][now.y][now.z]; q.push((node){now.x+dx[i],now.y+dy[i],now.z-1,dis[now.x+dx[i]][now.y+dy[i]][now.z-1]}); } } } } else { if(!vis[now.x][now.y][B[now.x][now.y]]) { if(dis[now.x][now.y][B[now.x][now.y]]>dis[now.x][now.y][0]+A[now.x][now.y]) { dis[now.x][now.y][B[now.x][now.y]]=dis[now.x][now.y][0]+A[now.x][now.y]; q.push((node){now.x,now.y,B[now.x][now.y],dis[now.x][now.y][B[now.x][now.y]]}); } } } } while(!q.empty())q.pop(); } ll xty,xtz,ytx,ytz,ztx,zty; int main() { n=init();m=init(); for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { B[i][j]=init(); B[i][j]=min(B[i][j],n+m+1); topt=max(B[i][j],topt); } } for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { A[i][j]=init(); } } xx=init();xy=init();yx=init();yy=init();zx=init();zy=init(); dijkstra(xx,xy); xty=dis[yx][yy][0]; xtz=dis[zx][zy][0]; dijkstra(yx,yy); ytx=dis[xx][xy][0]; ytz=dis[zx][zy][0]; dijkstra(zx,zy); ztx=dis[xx][xy][0]; zty=dis[yx][yy][0]; if(ytx+ztx<ans) { where='X'; ans=ytx+ztx; } if(xty+zty<ans) { where='Y'; ans=xty+zty; } if(xtz+ytz<ans) { where='Z'; ans=xtz+ytz; } if(ans==llINF) { printf("NO\n"); } else printf("%c\n"LLD,where,ans); return 0; } /* srO xudyh davidlee1999WTK linkct1999 zlser Orz */