Problem Description
There are apple trees planted along a cyclic road, which is metres long. Your storehouse is built at position on that cyclic road.
The th tree is planted at position , clockwise from position . There are delicious apple(s) on the th tree.
You only have a basket which can contain at most apple(s). You are to start from your storehouse, pick all the apples and carry them back to your storehouse using your basket. What is your minimum distance travelled?
There are less than 20 huge testcases, and less than 500 small testcases.
Input
First line: , the number of testcases.
Then testcases follow. In each testcase:
First line contains three integers, .
Next lines, each line contains .
Output
Output total distance in a line for each testcase.
Sample Input
2 10 3 2 2 2 8 2 5 1 10 4 1 2 2 8 2 5 1 0 10000
Sample Output
18 26
题意:
有一个圈,圈的长度是l,在正上方是0点,在圈上有n棵苹果树,给出每棵苹果树的位置和苹果的数量,现在一个人在0点的农场里,有一个小篮子,一次可以装k个苹果,问最少走多少距离可以把所有的苹果收回农场。
思路:
看了之后就觉得是贪心,怎么贪呢
对于摘苹果有几种情况:
1、正向去摘,然后按原路返回
2、反向去摘,然后按原路返回
3、走一圈
如果在圈上只剩下了k个苹果,可以一次摘走,如果这k个在一侧,或者在接近0点的两侧,那么走半圆是优的;
如果在两侧并且比较靠下方,那么直接走一圈就是优的。而且走一圈只可能出现一次,否则就可以用半圈来代替了。
题目中给出了所有的苹果不会超过10^5个,
让a[i]表示第i个苹果的位置,disr[i]表示正向摘完第i个需要的距离,disl[i]表示反向摘完第i个需要的距离,
然后通过它们找出如果没走过整圈需要的最小值,和走一个整圈需要的最小值,其中小的那个是结果。
如果k大于所有的苹果数,那么len的距离一定可以摘完,要特判一下最小值!!!
扩展:枚举+贪心
有n个点,用相同的线段去覆盖,当点在线段的端点才行,还有线段之间不相交
还有poj 1042 Gone Fishing类似
代码:
#include<bits/stdc++.h>
using namespace std;
#define LL __int64
struct node{
int x,a;
}p[100010];
int a[100010],cnt;
LL disl[100010],disr[100010];
int cmp(node t1,node t2){
return t1.x<t2.x ;
}
int main(){
int t,n,k;
int i,j;
LL len,ans;
scanf("%d",&t) ;
while( t-- ){
scanf("%d %d %d", &len, &n, &k) ;
for(i = 0 ; i < n ; i++) {
scanf("%d %d", &p[i].x, &p[i].a) ;
}
sort(p,p+n,cmp) ;
cnt = 1 ;
for(i = 0 ; i < n ; i++) {
for(j = 0 ; j < p[i].a ; j++)
a[cnt++] = p[i].x ;
}
memset(disl,0,sizeof(disl)) ;
memset(disr,0,sizeof(disr)) ;
for(i = 1 ; i < cnt ; i++) {
j = max(i-k,0) ;
disr[i] = disr[j] + 2*a[i] ;
}
for(i = cnt-1 ; i > 0 ; i--) {
j = min(i+k,cnt) ;
disl[i] = disl[j] + 2*(len-a[i]) ;
}
ans = 0 ;
for(i = 0 ; i < cnt ; i++) {
if( ans == 0 ) ans = disr[i] + disl[i+1] ;
else ans = min(ans,disr[i]+disl[i+1]) ;
}
for(i = 0 ; i+k+1 <= cnt ; i++)
ans = min(ans,disr[i]+disl[i+k+1]+len) ;
if( k >= cnt ) ans = min(ans,len) ;
printf("%I64d\n", ans) ;
}
return 0 ;
}