• 牛吃药


    牛吃药

    半个月之前Alice买了一些竹竿,拼接之后Alice把它截成等长的四段,围出一个正方形的牛棚用来养牛。由于Alice的畜牧经验不足,这头牛患了病。Alice找到当地的兽医开药,并药物拌入饲料喂给这头牛。

    假设这个牛棚是个边长为N的正方形,牛棚中所有的点描述为从(0,0)到(N,N)的坐标,牛棚的边缘的各点都堆有饲料,而其中只有M个点放置的是拌有药品的饲料。

    假设牛在吃完一堆饲料再吃下一堆时,只会选择与刚吃完这堆相邻近的饲料。现在这头牛需要吃K堆含药饲料才能痊愈,吃每堆饲料要花1分钟。
    若从吃完第一堆开始计时,请问这头牛最少要额外花几分钟才能达到吃药的目标

    数据输入

    第一行有三个整数N,M,K

    接下来有M行,每行两个整数表示拌入药物的饲料的坐标,题目保证给出的坐标在正方形的边缘

    1 ≤ N,M ≤105
    1 ≤K ≤ M
    0 ≤ xi,yi≤N
    xi与yi至少有一个为0或为N(保证坐标在正方形牛棚的边缘)

    数据输出

    输出一行,一个整数,代表牛吃到相应数量的药最短可能花费的时间

    样例1
    输入样例

    5 5 3
    5 3
    0 0
    0 4
    3 0
    1 5
    

    输出样例

    6
    

    提示

    输入样例的解如下图示,牛从E开始吃第一堆。吃完E点的第一堆开始计时,第1分钟在点(0,5)吃,第2分钟在点(0,4)吃,…直到第6分钟吃完(0,0)的饲料,吃了3次药达到目标,花费6分钟。当然,如果牛先从B开始然后顺时针吃C和E也可以,同样花费6分钟

    思路

    固定一个方向比如逆时针。枚举M个点,对每个点计算到逆时针接下来k个药的最短距离,枚举一遍后输出其最小值即可。如果将各坐标按四条边排序,就将二维转换成一维。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    //using std::abs;//这一行是? 
    struct plugs
    {
        int x,y;
        int distToNext;
        int distToOrigin;
        bool operator<(const plugs &b) const//这一行是运算符重载,定义比较方法 
        {
            return distToOrigin<b.distToOrigin;//按照规定的逆时针序号排序, <就是这个序号小于 
        }
    };
    
    int main(void)
    {
        //std::vector<plugs> s;
        vector<plugs> s;
        int i,x,y,N,M,K;
        plugs *p;
        p=(plugs*)malloc(sizeof(plugs));//定义指针,开辟空间 
        scanf("%d%d%d",&N,&M,&K);
    
        for(i=0;i<M;i++)
        {
            scanf("%d%d",&x,&y);
            p->x=x;
            p->y=y;
            p->distToNext=0;
            if (y==0 && 0<=x && x<N)//在下底边上 
                p->distToOrigin=x;//这里是开始一维编号,逆时针开始依顺序编号 
            else if ( x==N && 0<y && y<=N)//在右边 
                p->distToOrigin=N+y;
            else if ( y==N && 0<x && x<=N)//在上顶边 
                p->distToOrigin=3*N-x;
            else
                p->distToOrigin=4*N-y;
            s.push_back(*p);
        }//成功一维化,类似循环队列。 
    
        //std::sort(s.begin(),s.end());
        sort(s.begin(),s.end());//默认是升序排列,这里必须先排序才行 
        p->distToOrigin=s[0].distToOrigin+4*N;//这是减法借位 
        s.push_back(*p);//此处是特殊处理 
    
        for(i=0;i<M;i++)
            s[i].distToNext=s[i+1].distToOrigin-s[i].distToOrigin;//记录要前进的步数 
        //一维化彻底完成 
        int tmpSum=0,minVal=0x7FFFFFFF;//设置一个哨兵 
        K--;
        for(i=0;i<K;i++)
        {
            tmpSum+=s[i].distToNext;//排除起点记录,吃到k个含药的,要花的时间 
        }//此处是从s[0]开始吃药 
        for(i=0;i<M;i++)//开始枚举 
        {
            tmpSum=tmpSum+s[(i+K)%M].distToNext-s[i].distToNext;//核心 
            if(tmpSum<minVal)
                minVal=tmpSum;
        }
        printf("%d
    ",minVal);
        delete p;
        return 0;
    }
    

    -s[i].distToNext;先去除此次的起点,
    s[(i+K)%M].distToNext是此次的终点,更新一波,这样可以实现枚举。

  • 相关阅读:
    setTimeout 理解
    Git 使用规范流程
    JavaScript异步编程 ( 一 )
    javaScript模块化一
    javascript 知识点坑
    javaScript闭包
    函数式编程
    JavaScript的68个技巧一
    MySql 隐式转换
    MySQL优化
  • 原文地址:https://www.cnblogs.com/lingr7/p/10523221.html
Copyright © 2020-2023  润新知