ZOJ-4096 Postman(邮递员)(贪心)
Postman
Time Limit: 1 Second Memory Limit: 65536 KB
N letters have just arrived at the post office positioned at x=0, and the i-th letter should be posted to position x=ai . BaoBao, our beloved postman, will start his work from the post office and deliver all these letters by himself.
n封信件早已到达了位于原点的邮局,以及第i封信应该被送到ai这个位置,豹豹,我们亲爱的邮递员,将会在邮局开始他的工作,并且自个把所有信件送达
Unfortunately, BaoBao's backpack can only hold at most K letters each time (which means that if he wants to deliver some letter not in his backpack, he will have to go back to the post office and fetch it), so he may not be able to deliver all N letters in one go. Please note that BaoBao cannot temporarily drop a letter outside the post office and pick it back afterward.
不幸的是,豹豹的背包顶多一次容纳至多K封信(这意味着如果他想送更多信,他就得回邮局拿信),所以他不太可能一次就送完N封信。请注意,豹豹没法临时把一封信放在邮局外边,然后再把它拿回来
What's the minimum distance BaoBao has to travel to deliver all N letters?
豹豹送完N封信走的最短距离是什么?
It's NOT necessary that BaoBao ends his delivery in the post office.
豹豹没必要在邮局才结束他的工作(送完最后一封信之后任务立即结束)
Input(数据范围等参见http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=4096)
There are multiple test cases. The first line of the input contains an integer T , indicating the number of test cases. For each test case:
The first line contains two integers and (), indicating the total number of letters and the capacity of the backpack.
The second line contains integers (), indicating the destination of each letter.
It's guaranteed that the sum of over all test cases will not exceed .
Output
For each test case output one line containing one integer, indicating the minimum distance BaoBao has to travel to deliver all the letters, starting from the post office at .
Sample Input
2
5 3
-1 -2 3 -4 -5
6 3
1 0 -2 -1 1 2
Sample Output
13
6
Hint
For the first sample test case, BaoBao can first deliver the 1st and the 3rd letter (go to , then to , then to the post office), then deliver the 2nd, the 4th and the 5th letter (go to , then to , then to ), and ends his delivery at .
一看到最少距离,我们就需要制定一个策略来达到这个目的。首先注意到了原题数据范围存在正数与负数和0,也就是说在这条一维坐标轴两侧各存在一组数据,那么,如果没必要,肯定不能在轴两侧来回穿梭(极大的增加了距离),一定是单侧计数。而且,题目中说明:送完最后一封信任务即可结束,所以我们把最长的路走单程,也就是说放到最后一个送即可。
那么单侧计数时要注意什么呢?我们肯定要先送远的,因为如果先送近的,之后走远路的时候势必走过近的点,所以先送近信只会导致多走很多次近路,导致总路程增大。
所以我们从最端点计算,以k个点为一组,而且,就算一侧的点不足k个,那么送完之后势必经过原点,此时正好补充信件,恢复到k封信,所以这里不用再细分情况。
那么就有如下的思路:
- 输入时找出各个ai的绝对值的最大值,并分别把<0的数据和>0的数据分别放到不同的数组里(放入绝对值也可),=0的数据无所谓。
- 对<0的数据从小到大排序(或者对已有的绝对值从大到小排序),对>0的数据从大到小排序。
- 对单侧,每隔k个元素,加两倍ai路径(这是这个区间内最远的路径,其他的都包含在内)。
- 最后的答案减去一倍的之前统计的距离最大值即可
详情请见代码:
#include <iostream>
#include <cstdio>
#include <bits/stdc++.h>
#include <iomanip>
#include <cstring>
#include <cmath>
#define DETERMINATION main
#define lldin(a) scanf("%lld",&a)
#define din(a) scanf("%d",&a)
#define printlnlld(a) printf("%lld\n",a)
#define printlnd(a) printf("%d\n",a)
#define printlld(a) printf("%lld",a)
#define printd(a) printf("%d",a)
#define reset(a,b) memset(a,b,sizeof(a))
const int INF=0x3f3f3f3f;
using namespace std;
const double PI=acos(-1);
typedef long long ll;
typedef long double ld;
///Schlacht von Stalingrad
/**Although there will be many obstructs ahead,
the desire for victory still fills you with determination..**/
int left2[500000],right2[500000];
int zero;
bool cmp(int a,int b)
{
return a>b;
}
int DETERMINATION()
{
int t;
din(t);
while(t--)
{
int n,k;
din(n),din(k);
int tmp;
reset(left2,0);
reset(right2,0);
int cnt1=0,cnt2=0;
int most=-INF;
for(int i=1;i<=n;i++)
{
din(tmp);
if(tmp<0)
left2[cnt1++]=-tmp;//存入绝对值
else if(tmp>0)
right2[cnt2++]=tmp;
else
zero++;
most=max(most,abs(tmp));//找出最大值
}
sort(left2,left2+cnt1,cmp);//绝对值从大到小排序
sort(right2,right2+cnt2,cmp);
ll ans=0;
for(int i=0;i<cnt1;i+=k)
{
ans+=2*left2[i];
}
for(int i=0;i<cnt2;i+=k)
{
ans+=2*right2[i];
}
printlnlld(ans-(ll)most);
}
return 0;
}