题目地址:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=4096

题意


多组输入。

有n封信要送到指定地点,每次最多拿k封,重新拿信要回到位置0,求把所有信送完走的最小的距离

 

解题思路


贪心。

分x<0和x>0两部分,计算只去不回的距离(来回的距离*2即可)。

在坐标轴上从远往近(相对于位置0来说)贪心,每次都尽可能多的送信,用p记录每一段送信的最远距离,ans+=p。

最后取min(ans*2-左侧最远点,ans*2-右侧最远点),最后一次走的最远,且只去不回。

一定要从远往近贪心!!这样走的距离才最小!对最后一段送信的区间要特殊考虑下

<figcaption> 一种可能的情况 </figcaption>

 

好吧,我讲不清楚了(´・Д・)」具体看代码吧

 

ac代码


#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <ctype.h>
#include <set>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <sstream>
#define  maxn 100005
typedef long long ll;
using namespace std;
struct node{
    ll pos,num;//位置pos,要送num封信
    friend bool operator <(node a,node b)
    {
        return a.pos>b.pos;
    }
}l[maxn],r[maxn];
ll t,n,k,x;
ll half(node a[],ll numi)
{
   ll res=0,sum=0,p=0;//记录每一段的起始位置
   if(numi>=1) p=a[0].pos;
   for(ll i=0;i<numi;)
   {
       sum=0;
       while(i<numi)
       {
           sum+=a[i].num;
           if(sum==k)
           {
               res+=p;
               i++;
               if(i<numi)
                p=a[i].pos;
               else p=0;
               break;
           }
           else if(sum>k)
           {
               res+=p;
               a[i].num-=(k-(sum-a[i].num));
               p=a[i].pos;
               break;
           }
           else //sum<k
               i++;
       }
   }
   if(p!=0)//最后一段的路程还没有记录到结果中
       res+=p;
    //cout<<"res"<<res<<endl;
    return res;
}
int main()
{
    //freopen("/Users/zhangkanqi/Desktop/11.txt","r",stdin);
    scanf("%lld",&t);
    while(t--)
    {
        memset(l,0,sizeof(l));
        memset(r,0,sizeof(r));
        ll ans = 0, numl = 0, numr = 0;
        scanf("%lld %lld", &n, &k);
        for (ll i = 0; i < n; i++)
        {
            scanf("%lld", &x);
            if (x > 0)
            {
                r[numr].pos = x;
                r[numr++].num++;
            }
            else if (x < 0)
            {
                l[numl].pos = -x;
                l[numl++].num++;
            }
        }
        sort(l, l + numl);
        sort(r, r + numr);
        ans+=half(l,numl);
        ans+=half(r,numr);
        printf("%lld\n",min(ans*2-l[0].pos,ans*2-r[0].pos));
    }
    return 0;
}