洛谷 P11768 破自行车

题目背景

某个夏天,18071 号工作室的 staff 集体转业了。辗转至年末,天依终于在 40312 号工作室拉到了合作。但是……看着编号的差距,按时到班可不是一件容易的事情。

七点半,闹铃声响起,早高峰即将迎接起床气!

题目描述

天依住在的城市像一个无穷大的曼哈顿。如果把城市地图放在平面直角坐标系中,任何一个整点 ( x , y ) (x,y) (x,y) 都是一个十字路口。天依家门口的十字路口为 ( 0 , 0 ) (0,0) (0,0),天依需要从这里出发,尽快抵达工作室所在的十字路口 ( a , b ) (a,b) (a,b)。每分钟,天依可以从她所在的十字路口 ( x , y ) (x,y) (x,y) 移动至 ( x + 1 , y ) (x+1,y) (x+1,y) ( x − 1 , y ) (x-1,y) (x1,y) ( x , y + 1 ) (x,y+1) (x,y+1) 或者 ( x , y − 1 ) (x,y-1) (x,y1)

天依怎么会走路上班呢?她可以使用一辆很快很邪门的破自行车!骑上它,天依可以从 ( x , y ) (x,y) (x,y) 瞬间冲到 ( x + l , y ) (x+l,y) (x+l,y) ( x , y + l ) (x,y+l) (x,y+l) ( x − l , y ) (x-l,y) (xl,y) ( x , y − l ) (x,y-l) (x,yl) 四个位置中的一个,不花费任何时间。但为了避免破自行车散架,天依最多使用 k k k 次自行车。

那么,在破自行车的助力下,天依至少需要多少时间才能从 ( 0 , 0 ) (0,0) (0,0) 出发到达 ( a , b ) (a,b) (a,b) 呢?

因为工作室经常搬家,所以有多组测试数据。

输入格式

第一行一个整数 T T T,表示测试数据组数。

接下来 T T T 行,每行四个整数 a , b , k , l a,b,k,l a,b,k,l,分别表示工作室所在的十字路口的横纵坐标,自行车的使用次数限制和自行车的移动距离。

输出格式

输出 T T T 行,第 i i i 行一个整数,表示第 i i i 组数据中到达工作室的最小时间。

输入输出样例 #1

输入 #1

3
4 5 3 2
1 1 4 5
8 8 4 8

输出 #1

3
2
0

说明/提示

样例解释:

我们使用 > > > 表示猛冲, → \to 表示行走。

对于样例一,一种可能的移动方式是: ( 0 , 0 ) > ( 2 , 0 ) → ( 3 , 0 ) → ( 4 , 0 ) → ( 4 , 1 ) > ( 4 , 3 ) > ( 4 , 5 ) (0,0)>(2,0)\to(3,0)\to(4,0)\to(4,1)>(4,3)>(4,5) (0,0)>(2,0)(3,0)(4,0)(4,1)>(4,3)>(4,5)

对于样例二,一种可能的移动方式是: ( 0 , 0 ) → ( 0 , 1 ) → ( 1 , 1 ) (0,0)\to(0,1)\to(1,1) (0,0)(0,1)(1,1)

对于样例三,一种可能的移动方式是: ( 0 , 0 ) > ( 0 , 8 ) > ( 8 , 8 ) (0,0)>(0,8)>(8,8) (0,0)>(0,8)>(8,8)

数据规模与约定

本题采用捆绑测试。 仅当你通过了该子任务的全部测试数据才能获得该子任务的分值。

对于 100 % 100\% 100% 的数据, 1 ≤ T ≤ 1 0 5 1 \leq T \leq 10^5 1T105 0 ≤ a , b , k , l ≤ 1 0 9 0 \leq a,b,k,l\leq 10^{9} 0a,b,k,l109

对于不同的子任务,作如下约定:

子任务编号 T T T a , b , l a,b,l a,b,l k k k特殊性质子任务分值
1 1 1 ≤ 1 0 5 \le10^5 105 ≤ 1 0 9 \le10^9 109 = 0 =0 =0 15 15 15
2 2 2 ≤ 10 \le10 10 ≤ 10 \le10 10 ≤ 10 \le10 10 10 10 10
3 3 3 ≤ 10 \le10 10 ≤ 1 0 9 \le10^9 109 ≤ 20 \le20 20 15 15 15
4 4 4 ≤ 10 \le10 10 ≤ 1 0 9 \le10^9 109 ≤ 1 0 3 \le10^3 103 20 20 20
5 5 5 ≤ 1 0 5 \le10^5 105 ≤ 1 0 9 \le10^9 109 ≤ 1 0 9 \le10^9 109 a , b ≤ l a,b\le l a,bl 15 15 15
6 6 6 ≤ 1 0 5 \le10^5 105 ≤ 1 0 9 \le10^9 109 ≤ 1 0 9 \le10^9 109 25 25 25

贪心算法

思路:移动的每一步尽量使用破自行车猛冲。
如果没有自行车,那所需时间就是a+b。
横纵方向,先任意选择一个方向尽量使用破自行车猛冲,然后再换方向尽量使用破自行车猛冲。

横纵都冲完后,已经是最靠近(a,b)点的位置了,然后再判断要不要冲出(a,b)之外。
例如当目标点为 (5,5),l=3时,按照我们已有的策略我们会先移动到 (3,3),再一步一步走过去,花费 4 分钟;但其实可以先移动到 (6,6)再走过去,花费 2 分钟。

代码如下

#include<iostream>
using namespace std;

int T,a,b,k,l,ans1,ans2;
//ans1接收横向所需时间,ans2接收纵向所需时间

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);

    /*下面两行代码绝对不能放在这,如果起初l==0,除数为0会报错,显示RE
    int x=a/l;
    int y=b/l;
    */
    
    cin>>T;
    while(T)
    {
        cin>>a>>b>>k>>l;
        

        if(l==0)
        {
            cout<<a+b<<'\n';
            T--;//一定要在这里有个T--,因为这里也处理了一组数据
            continue;
        }
        int x=a/l;//横向能冲的最大次数
        int y=b/l;//纵向能冲的最大次数
        
        if(k>=x)
        {
            k-=x;
            ans1=a-x*l;
        }
        else
        {
            ans1=a-k*l;
            k=0;
        }

        if(k>=y)
        {
            k-=y;
            ans2=b-y*l;
        }
        else
        {
            ans2=b-k*l;
            k=0;
        }

		//判断需不需要冲到(a,b)外面去
        if(ans1>l/2&&ans2>l/2&&ans2>ans1&&k)
        {
            ans2=l-ans2;
            k--;
        }
        if(ans1>l/2&&k)
        {
            ans1=l-ans1;
            k--;
        }
        if(ans2>l/2&&k)
        {
            ans2=l-ans2;
            k--;
        }
        T--;
        cout<<ans1+ans2<<'\n';
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值