题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=6653
题意:
现在有一个二维平面的城市,每个点都是一个十字分叉路口。点和点之间的线是道路,像一般的红绿灯一样,如果你右拐是不需要等待的,如果要左转,需要等待a分钟,直走需要等待b分钟。现在小A要去到点 ( x , y ) (x,y) (x,y) ,他现在正开着车从 ( 0 , − 1 ) (0,-1) (0,−1) 开向 ( 0 , 0 ) (0,0) (0,0) ,他不需要很快到达,只希望等待红灯的时间越少越好,现在问他最少要等待多少的时间能到达目的地。
做法:
因为你可以无限右转,所以就像下面的图一样,你可以把一个格子的四个角用一个坐标代替(左上角右上角随意),我的图是直接用了左上角的点代替。这样之后你就可以把车看成是一个个格子的移动。
这样的话你会发现,如果你的移动是上下左右,那么你的花费就是直行的 b b b,如果是斜着走,那么就是左转的 a a a,斜着走一步相当是两个直走,所以你就可以根据 a a a 和 2 b 2b 2b的关系来进行分类讨论走法来 O ( 1 ) O(1) O(1)得到答案。
当然因为是格子的原因,所以我们要对包含答案坐标的四个格子分别求一次最佳答案来取一个最小值即可。
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll a,b,ex,ey;
ll Abs(ll x){
if(x<0) return -x;
return x;
}
ll deal(ll x,ll y){
ll sx=0,sy=0,ret=0;
ll gx=Abs(sx-x),gy=Abs(sy-y),sub=max(gx,gy)-min(gx,gy);
if(a<=b){
ret+=max(gx,gy)*a;
}
else if(a<=2*b){
ret+=a*min(gx,gy)+b*sub;
}
else{
ret+=b*(gx+gy);
}
return ret;
}
int main(){
int t;scanf("%d",&t);
while(t--){
scanf("%lld%lld%lld%lld",&a,&b,&ex,&ey);
ll ans=deal(ex,ey);
ans=min(ans,deal(ex-1,ey));
ans=min(ans,deal(ex,ey+1));
ans=min(ans,deal(ex-1,ey+1));
printf("%lld\n",ans);
}
return 0;
}