original link - http://acm.hdu.edu.cn/showproblem.php?pid=6670
题意:
给出n个矩阵,起点到终点,可以往四个方向移动,被 k k k个矩形覆盖时,速度为 k + 1 k+1 k+1,边也算覆盖。求最短时间。
解析:
将所有坐标离散化,建网格图(400*400)。
两个点之间的距离已经可以计算了,关键是被多少个矩形覆盖。
首先我们二维差分一下,处理出每个点被覆盖的次数。但是两个点之间的线段被覆盖几次还是不能算出来。所以我们将坐标两倍化,取两个点中间的点来判断被覆盖的次数。
这个不是简单的 b f s bfs bfs,最近的点跑到终点的路径可能很长,所以不能跑到就 b r e a k break break。
代码:
#include
using namespace std;
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=a;i>=b;i--)
#define LL long long
const int maxn=900;
const int di[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
struct Uni{
int a[maxn];
int num=0;
void push(int val){
a[++num]=val;
}
void init(){
sort(a+1,a+1+num);
num=unique(a+1,a+1+num)-a-1;
}
int pos(int val){
return lower_bound(a+1,a+1+num,val)-a;
}
int ori(int pos){
return a[pos];
}
}X,Y;
struct point{
int x,y;
};
struct node{
point a,b;
}e[maxn];
struct Node{
int x,y;
double dis;
Node(int x,int y,double dis):x(x),y(y),dis(dis){}
bool operator<(const Node&A)const{
return dis>A.dis;
}
};
LL val[maxn][maxn];
double dis[maxn][maxn];
bool vis[maxn][maxn];
//pair pre[maxn][maxn];
int main(){
//freopen("data.in","r",stdin);
//freopen("data.out","w",stdout);
int t;scanf("%d",&t);
while(t--){
memset(val,0,sizeof val);
X.num=Y.num=0;
int n;scanf("%d",&n);
point st,en;
rep(i,1,n+1){
scanf("%d%d%d%d",&e[i].a.x,&e[i].a.y,&e[i].b.x,&e[i].b.y);
X.push(e[i].a.x);
X.push(e[i].b.x);
Y.push(e[i].a.y);
Y.push(e[i].b.y);
}
X.init(),Y.init();
rep(i,1,n+1){
int &x=e[i].a.x,&y=e[i].a.y,&xx=e[i].b.x,&yy=e[i].b.y;
x=X.pos(x);
y=Y.pos(y);
xx=X.pos(xx);
yy=Y.pos(yy);
if(i<=n)
val[x*2][y*2]++,
val[x*2][yy*2+1]--,
val[xx*2+1][y*2]--,
val[xx*2+1][yy*2+1]++;
}
rep(i,1,X.num*2+1){
rep(j,1,Y.num*2+1){
val[i][j]+=val[i-1][j]+val[i][j-1]-val[i-1][j-1];
dis[i][j]=1e18;
vis[i][j]=0;
}
}
st=e[n+1].a,en=e[n+1].b;
dis[st.x][st.y]=0;
priority_queue<Node>Q;
Q.push(Node(st.x,st.y,0));
while(!Q.empty()){
Node P=Q.top();Q.pop();
if(fabs(dis[P.x][P.y]-P.dis)>1e-9)continue;
vis[P.x][P.y]=1;
rep(i,0,3){
int x=P.x+di[i][0],y=P.y+di[i][1];
if(x<1||x>X.num||y<1||y>Y.num||vis[x][y])continue;
LL Dis=abs(X.ori(x)-X.ori(P.x))+abs(Y.ori(y)-Y.ori(P.y));
LL Speed=val[(x*2+P.x*2)/2][(y*2+P.y*2)/2]+1;//min(val[x][y],val[P.x][P.y])+1;
double tim=1.0*Dis/Speed;
if(dis[x][y]>dis[P.x][P.y]+tim){
dis[x][y]=dis[P.x][P.y]+tim;
Q.push(Node(x,y,dis[x][y]));
//pre[x][y]={P.x,P.y};
}
}
}
printf("%.5f\n",dis[en.x][en.y]);
/*int x=en.x,y=en.y;
while(1){
printf("%d %d, dis is %.4f\n",X.ori(x),Y.ori(y),dis[x][y]);
if(x==st.x&&y==st.y)break;
pair P=pre[x][y];
x=P.first;
y=P.second;
}*/
}
}