题意
一座桥,桥两侧各有 n 个人,每个人都想去桥对面休息 x 分钟后再返回(必须休息够 x 分钟才能被背回去),问你满足所有人的愿望,最少需要多少分钟(你背一个老人过一次桥需要 t 分钟)
思路
最优的办法是(前 2 n 次)每一次过桥先背一个人去对面休息,等到所有(2 n个)人都到了(相对于自己一开始的位置的)桥对面,然后,这时候自己应该在自己最开始的位置,而此时每个人的休息所剩时间应该是:
x x-2t x-4t … x-2*(n-1)t | x-t x-3t x-5t … x-(2n-1)t
(自己此时应该在左边,假设左边是起始位置) ( dis = x- 2 * ( n - 1 ) t )
这个时候应该判断是不是能立即背着所剩休息时间最少 ( dis ) 的人过桥
如果能立马走,那么对面所剩休息时间最少的人肯定也能立即走(因为桥对面的所剩休息时间最少的人比桥这面的人时间还要少( x - ( 2 n - 1 ) t < x - 2 * ( n - 1 ) t )),所以最后答案就是 2 * n * 2 * t
如果不能立马走,这时候应该判断,自己在桥这边等待的时间是不是 < 过桥的时间:
如果小于,那就等着桥这边的休息结束,然后在过桥,这时候桥对面肯定能立即走了,最后答案就是 2 * n * 2 * t + dis
如果大于,那就去桥对面,这时候桥对面的休息时间所剩最少的人时间应该是
x - 2nt(过桥花费 t )
同理判断能不能立即走,如果可以答案就是2 * n * 2 * t + t
如果不行,那么也不需要过桥了(因为这个人就是全场休息时间所剩最少的人,等他是最优的),直接等着他休息结束,最后答案就是 2 * n * 2 * t + t + x - 2 * n * t
代码
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn=1e7+10;
int main()
{
ll n,x,t,T;
scanf("%lld",&T);
while(T--)
{
scanf("%lld%lld%lld",&n,&x,&t);
if(2*(n-1)*t>=x) printf("%lld\n",2*n*2*t);
else
{
ll dis=x-2*(n-1)*t;
if(dis<=t) printf("%lld\n",2*n*2*t+dis);
else
{
if(2*n*t>=x) printf("%lld\n",2*n*2*t+t);
else printf("%lld\n",2*n*2*t+t+x-2*n*t);
}
}
}
return 0;
}