Delicious Apples
Time Limit: 5000/3000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Others)Total Submission(s): 1120 Accepted Submission(s): 370
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 i th tree is planted at position xi , clockwise from position 0 . There are ai delicious apple(s) on the i th 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 i th tree is planted at position xi , clockwise from position 0 . There are ai delicious apple(s) on the i th 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
Recommend
长度为l米的环形道路有n棵苹果树,每棵树坐标xi有ai个苹果,用容量为K的篮子全部搬回位置为0的储藏室,最少要走多少米?
思路:
以苹果为对象进行考虑。把苹果以储藏室为中点分为在其左边和在其右边两堆,如果不考虑走整个环形路径的话,左右边的苹果分别从左右去取就行了。
而环形路径最多只需要走一次,我们可以枚举这次拿了哪些苹果。详见代码注释。
aiai
#include <cstdio>
#include <algorithm>
using namespace std;
const int MAX = (int)1e5 + 10;
///把苹果以storehouse为中点分为在其左边和在其右边两堆
long long distL[MAX], distR[MAX];///某一边苹果距storehouse的距离(从0开始计数)
long long cntL[MAX], cntR[MAX];///将某一边的前n个苹果全部搬回去需要走的长度(从1开始计数)
int main(void) {
int T;
scanf("%d", &T);
while (T--) {
int l, n, k;
scanf("%d%d%d", &l, &n, &k);///路径长度、苹果树个数、篮子容量
int numL = 0, numR = 0;///左边和右边的苹果计数
///把每棵树上的苹果以storehouse为中点分为在其左边和在其右边两堆
for (int i = 0; i < n; ++i) {
int x, a;
scanf("%d%d", &x, &a);
for (int j = 0; j < a; ++j) {
if (x <= l / 2) {
distR[numR++] = x;
}
else {
distL[numL++] = l - x;
}
}
}
///每一堆按距离storehouse的长度由近到远排序
sort(distL, distL + numL);
sort(distR, distR + numR);
///每一堆计算cntL数组
///注:cnt的苹果从1开始计数,dist的苹果从0开始计数
for (int i = 0; i < numL; ++i) {
if (i < k) {///前k个苹果,只要走到第k个苹果处来回一趟就够了
cntL[i + 1] = distL[i] * 2;
}
else {///之后的,走到第i个苹果处来回一趟可取走k个,
///而前 i - k个苹果需要的步数已经被计算出来了(在cntL[i - k + 1]中)
cntL[i + 1] = distL[i] * 2 + cntL[i - k + 1];
}
}
///同理计算cntR
for (int i = 0; i < numR; ++i) {
if (i < k) {
cntR[i + 1] = distR[i] * 2;
}
else {
cntR[i + 1] = distR[i] * 2 + cntR[i - k + 1];
}
}
///不考虑走环形的情况,分别从两边摘走所有苹果,答案如下
long long ans = cntL[numL] + cntR[numR];
///考虑走环形的情况,易知最多只需要走一个环形
///而且走环形时带走离storehouse最远的苹果是最优的
///认为走环形时带走了k个苹果不影响结果,
///所以我们枚举走环形时从右边带走了多少个苹果
for (int i = 0; i <= min(k,numR); ++i) {
int right = max(0,numR - i); ///不走环形时从右边带走的苹果数
int left = max(0,numL - (k - i));///不走环形时从左边带走的苹果数
ans = min(ans, l + cntL[left] + cntR[right]);///总路程
}
printf("%I64d\n", ans);
}
return 0;
}