【B - Stairs and Elevators CodeForces - 967C 】(贪心/二分)

链接:http://codeforces.com/problemset/problem/967/C

题意:有n层楼,每层楼都有m个区,需要通过走楼梯或者乘电梯上下楼,相邻区之间移动和爬一层楼梯需要一个单位时间,乘电梯的最大速度为v层每单位时间.现问从x1层y1区移动到x2层y2区需要的最少的时间为多少.

思路:画图分析可以知道找到突破口:假设x1< x2,先比较楼梯,二分查找到x1左侧最近的楼梯,x1和x2之间的任意一个楼梯,x2右侧最近的楼梯,然后比较3条路线的最小值,同理得到乘电梯的最小值,取较小即为答案.,二分可以用stl完成,但是注意考虑边界,以及此处lower_bound与upper_bound不同(必须使用upper_bound)。

代码:

//gcd性质:数字ai最多有log2(ai)个质因子
#include<cstdio>
#include<math.h>
#include<string.h>
#include<queue>
#include<map>
#include<math.h>
#include<iostream>
#include<set>
#include<vector>
#include<string>
#include<algorithm>
#define ll long long
#define mem(x,y) memset(x,y,sizeof(x));
#define pi acos(-1.0)
using namespace std;
const int maxn=100006;
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll powmod(ll a ,ll b,ll mod){ll ans=1;while(b){if(b%2)ans=ans*a%mod;a=a*a%mod;b/=2;}return ans;}
int a[maxn];
int b[maxn];

int main(){
	int n,m,cl,ce,v;
	scanf("%d%d%d%d%d",&n,&m,&cl,&ce,&v);
	for(int i=0;i<cl;i++)scanf("%d",&a[i]);
	for(int i=0;i<ce;i++)scanf("%d",&b[i]);
	int q;
	scanf("%d",&q);
	while(q--){
		int x1,x2,y1,y2;
		scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
		int minn=0x3f3f3f3f;
		if(x1==x2)minn=abs(y1-y2);
		else{
			int p=upper_bound(a,a+cl,y1)-a;
			if(p<cl)minn=min(minn,abs(x1-x2)+abs(y1-a[p])+abs(y2-a[p]));
			p--;
			if(p>=0)minn=min(minn,abs(x1-x2)+abs(y1-a[p])+abs(y2-a[p]));

			p=upper_bound(b,b+ce,y1)-b;
			if(p<ce)minn=min(minn,(int)ceil(abs(x1-x2)*1.0/v)+abs(y1-b[p])+abs(y2-b[p]));
			p--;
			if(p>=0)minn=min(minn,(int)ceil(abs(x1-x2)*1.0/v)+abs(y1-b[p])+abs(y2-b[p]));
		}
		printf("%d\n",minn);
	}
}


扫描二维码关注公众号,回复: 1896410 查看本文章





猜你喜欢

转载自blog.csdn.net/running_acmer/article/details/80925442