2015 Multi-University Training Contest 2 1004 Delicious Apples(HDU5303)

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?

1n,k105,ai1,a1+a2+...+an105
1L109
0x[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 .
 

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
wange2014   |   We have carefully selected several similar problems for you:   5315  5314  5313  5312  5311 
 

题意:

长度为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;
}






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值