题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5303
Problem Description
There are
n apple trees planted along a cyclic road, which is
L metres long. Your storehouse is built at position
0 on that cyclic road.
The ith tree is planted at position xi, clockwise from position 0. There are ai delicious apple(s) on the ith tree.
You only have a basket which can contain at most K 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?
1≤n,k≤105,ai≥1,a1+a2+...+an≤105
1≤L≤109
0≤x[i]≤L
There are less than 20 huge testcases, and less than 500 small testcases.
The ith tree is planted at position xi, clockwise from position 0. There are ai delicious apple(s) on the ith tree.
You only have a basket which can contain at most K 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?
1≤n,k≤105,ai≥1,a1+a2+...+an≤105
1≤L≤109
0≤x[i]≤L
There are less than 20 huge testcases, and less than 500 small testcases.
Input
First line:
t, the number of testcases.
Then t testcases follow. In each testcase:
First line contains three integers, L,n,K.
Next n lines, each line contains xi,ai.
Then t testcases follow. In each testcase:
First line contains three integers, L,n,K.
Next n lines, each line contains xi,ai.
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
Source
题意:
一个长为 L 的环行路线。有 n 颗苹果树,每颗苹果树上有 a[i] 个苹果,一个人在0点(仓库的位置),他有一个篮子,篮子每次最多仅仅能装 k 个苹果。求要装全然部的苹果而且回到仓库的最小路程;给出的苹果树坐标是按顺时针的。
官方题解:
PS:
贪心。把环从中间分为两段。分左右两条线。
利用 a[i] 数组记录每一个苹果所在的苹果树的位置,之后再将苹果依照所在的位置进行排序一下。
所以我们就知道了每次摘 k 个苹果的路程是最远的那个苹果所在的位置。
再用 sum[i] 表示摘第 i 个苹果时的最小代价和。
依据背包的思想得到:
if ( i <= k )
sum[i] = d[i]
else
sum[i] = d[i] + sum[i-k]注意:
另一种情况是在最后当剩下的苹果少于等于 k 个时,也许一次性绕环一圈拿完最后的k个所需的路程更少。
枚举剩下的最后k个!
代码例如以下:
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
#define LL __int64
const int maxn = 100047;
vector <int> v1, v2;
LL a[maxn];
LL sum1[maxn], sum2[maxn];
int main()
{
int t;
int n, k, l;
scanf("%d",&t);
while(t--)
{
scanf("%d%d%d",&l,&n,&k);
int pos, num;
int h = 0;
for(int i = 0; i < n; i++)
{
scanf("%d%d",&pos,&num);
for(int j = 0; j < num; j++)
{
a[++h] = pos;
}
}
k = min(h,k);
v1.clear();
v2.clear();
for(int i = 1; i <= h; i++)
{
if(a[i]*2 < l)
{
v1.push_back(a[i]);
}
else
{
v2.push_back(l - a[i]);
}
}
memset(sum1,0,sizeof(sum1));
memset(sum2,0,sizeof(sum2));
sort(v1.begin(), v1.end());
sort(v2.begin(), v2.end());
int len1 = v1.size(), len2 = v2.size();
for(int i = 0; i < len1; i++)
{
int id = i+1;
if(id <= k)
{
sum1[id] = v1[i];
}
else
{
sum1[id] = v1[i]+sum1[id-k];
}
}
for(int i = 0; i < len2; i++)
{
int id = i+1;
if(id <= k)
{
sum2[id] = v2[i];
}
else
{
sum2[id] = v2[i]+sum2[id-k];
}
}
LL ans = 2*(sum1[len1]+sum2[len2]);//来回
int t1, t2;
for(int i = 0; i <= k && i <= len1; i++)
{
t1 = len1 - i;
t2 = len2-(k-i);
if(t2 < 0)
{
t2 = 0;
}
ans = min(ans,2*(sum1[t1]+sum2[t2])+l);//最后不足k个绕行一圈所有摘走
}
printf("%I64d\n",ans);
}
return 0;
}