[Usaco2018 Feb]Slingshot 多种实现-附完整代码

这篇博客介绍了Usaco2018 Feb竞赛中关于Slingshot问题的解决方案,包括暴力算法的PHP实现、使用树形数组优化的PHP版本,以及多进程暴力算法的Python版本。文章详细阐述了问题说明、输入输出格式,并提供了样例输入输出。
摘要由CSDN通过智能技术生成
 

原题参考:http://www.usaco.org/index.php?page=viewproblem2&cpid=816&lang=zh

问题说明

FarmerJohn最讨厌的农活是运输牛粪。为了精简这个过程,他产生了一个新奇的想法:与其使用拖拉机拖着装满牛粪的大车从一个地点到另一个地点,为什么不用一个巨大的便便弹弓把牛粪直接发射过去呢?(事实上,好像哪里不太对……)FarmerJohn的农场沿着一条长直道路而建,所以他农场上的每个地点都可以简单地用该地点在道路上的位置来表示(相当于数轴上的一个点)。FJ建造了N个弹弓(1≤N≤10^5),其中第i个弹弓可以用三个整数xi,yi以及ti描述,表示这个弹弓可以在ti单位时间内将牛粪从位置xi发射到位置yi。FJ有M堆牛粪需要运输(1≤M≤10^5)。第j堆牛粪需要从位置aj移动到位置bj。使用拖拉机运输牛粪,经过路程d需要消耗d单位时间。FJ希望通过对每一堆牛粪使用至多一次弹弓来减少运输时间。FJ驾驶没有装载牛粪的拖拉机的时间不计。对这M堆牛粪的每一堆,在FJ可以在运输过程中使用至多一次弹弓的条件下,帮助FJ求出其最小运输时间。
 

输入格式(文件名:slingshot.in):

输入的第一行包含N和M。下面N行,每行用xi,yi,ti(0≤xi,yi,ti≤10^9)描述了一个弹弓。最后M行用aj和bj描述了需要移动的牛粪。
 

输出格式(文件名:slingshot.out):

输出M行,每堆牛粪一行,表示运输这堆牛粪需要的最短时间。
 

输入样例:

3

0 10 1

13 8 2 

12

5 2 

20 7

输出样例:

4

3

10

在这里,第一堆牛粪需要从位置1移动到位置12。不使用弹弓的话,会消耗11单位时间。但是,如果使用第一个弹弓,只需消耗1单位时间移动到位置0(弹弓的发射点),1单位时间将弹弓通过空中弹射并着陆在位置10(弹弓的目的地),然后2单位时间把牛粪移动到位置12。第二堆牛粪的最佳移动方案是不使用弹弓,第三堆牛粪应该使用第二个弹弓。

实现

暴力算法(PHP版本)

<?php

/**
 * 牛粪弹弓基类
*/
class SlingshotBase
{
    /**
     * @var  弹弓数组
    */
    public $slingshot_desc = array();

    /**
     * @var 牛粪数组
    */
    public $cow_dung_position = array();

   /**
    * @var 最小步数数组
   */
    public $mininum_steps = array();

   /**
    * @var 异常信息
   */
    public $error = array();

    /**
     * @var 弹弓数
    */
    public $n = 0;

    /**
     * @var 牛粪数
    */
    public $m  = 0;

    /**
     * 构造函数  
    */
    public function __construct($filename)
    {
        $contents_from_file = file($filename, FILE_IGNORE_NEW_LINES); //忽略文件末尾的换行符
        if (empty($contents_from_file) || count($contents_from_file) < 1) {
            throw new Exception('读取文件失败');
        }

        $n = 0;
        $m = 0;

        foreach ($contents_from_file as $idx => $line) {
            $line_split = preg_split("/\s+/", $line); //多个空格分割

            if ($idx < 1) {
                $this->_nm($n, $m, $idx, $line_split); //第一行,构建 n, m
            } else if ($idx <= $n   ) {
                $this->_slingshot($idx, $line_split); // 1< i< n,构建弹弓数组
            } else if ($idx <= $n + $m ) {
                $this->_cowdung($idx, $line_split); // n < i < m,构建牛粪数组
            } else {
                break; //忽略,其他行
            }
        }

        if (!empty($this->error)) {
            throw new Exception(implode("\r\n", $this->error));
        }

        $this->n = $n;
        $this->m = $m;
    }

    /**
     * 构建变量: $n 和 $m
     * @param: $n int return 
     * @param: $m int return
     * @param: $idx int  当前行号,异常时给出行号信息
     * @param: $line_split = array(int,int) 
    */
    private function _nm(&$n, &$m, $idx, $line_split)
    {
        if (count($line_split) != 2) {
            array_push($this->error, '第[' . $idx . ']行格式不对: 只能包含n m 2个数字并且以空格分隔');
        } else {
            $n = $line_split[0];
            $m = $line_split[1];
        }
    }

    /**
     * 构建类变量: $this->slingshot_desc
     * @param: $idx int  当前行号,异常时给出行号信息
     * @param: $line_split = array(int,int)
   
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值