zoukankan      html  css  js  c++  java
  • 2015 Multi-University Training Contest 2 hdu 5303 Delicious Apples

    Delicious Apples

    Time Limit: 5000/3000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)
    Total Submission(s): 1057    Accepted Submission(s): 354


    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?

    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
     
    解题:核心思想是贪心,关键在于枚举最后剩下的K个苹果。
     
    先把圆分成两半,用sum[i]算出到i最小需要多长路
     
     
    为什么是sum[i] = sum[i-k] + L[i]呢?
     
    这个其实是倒推!很明显,最后可能从前开始的不足K个,为什么不是从前面推呢?
     
    很明显,无论是从前面推还是后面推,其包含的K长度的区间个数是一定的,
     
    但是从后面推得到好处就是和会更少!
     
    这里体现了传说中的贪心思想。
     
    明显从后面推,前面部分的值更少
     
    最后我们需要枚举K个长度的区间,横跨两个半圆
    LL ret = (sum[Lsize][0] + sum[Rsize][1])<<1;
    这句话表示纯粹的使用不环绕圆的方式取完所有苹果的最短路径,是的最短,因为前面贪心了嘛。
     

    int a = Lsize - i; 表示的是什么呢?表示从左半圆选择i个 那么剩下的部分不跨圆,继续使用拿完原路返回策略
    int b = max(0,Rsize - (K - i)); 剩下的 K- i个采用拿了原路返回的策略
    ret = min(ret,((sum[a][0] + sum[b][1])<<1) + Len); 那么这K个,我们采用拿了 不原路返回,采用绕圆的方法

    所以多了Len 

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 typedef long long LL;
     4 const int maxn = 100010;
     5 LL d[maxn],tot,sum[maxn][2];
     6 vector<LL>L,R;
     7 int main() {
     8     int kase,n,K,m,pos;
     9     LL Len;
    10     scanf("%d",&kase);
    11     while(kase--) {
    12         scanf("%d%d%d",&pos,&n,&K);
    13         L.clear();
    14         R.clear();
    15         Len = pos;
    16         for(int i = tot = 0; i < n; ++i) {
    17             scanf("%d%d",&pos,&m);
    18             for(int j = 0; j < m; ++j)
    19                 d[tot++] = pos;
    20         }
    21         for(int i = 0; i < tot; ++i) {
    22             if(d[i]*2 < Len) L.push_back(d[i]);
    23             else R.push_back(Len - d[i]);
    24         }
    25         sort(L.begin(),L.end());
    26         sort(R.begin(),R.end());
    27         int Lsize = L.size(),Rsize = R.size();
    28         sum[0][0] = sum[0][1] = 0;
    29         for(int i = 0; i < Lsize; ++i)
    30             if(i + 1 <= K) sum[i + 1][0] = L[i];
    31             else sum[i + 1][0] = sum[i - K + 1][0] + L[i];
    32         for(int i = 0; i < Rsize; ++i)
    33             if(i + 1 <= K) sum[i+1][1] = R[i];
    34             else sum[i+1][1] = sum[i-K+1][1] + R[i];
    35         LL ret = (sum[Lsize][0] + sum[Rsize][1])<<1;
    36         for(int i = 0; i <= Lsize && i <= K; ++i) {
    37             int a = Lsize - i;
    38             int b = max(0,Rsize - (K - i));
    39             ret = min(ret,((sum[a][0] + sum[b][1])<<1) + Len);
    40         }
    41         cout<<ret<<endl;
    42     }
    43     return 0;
    44 }
    View Code
  • 相关阅读:
    半夜删你代码队 Day6冲刺
    半夜删你代码队 Day5冲刺
    半夜删你代码队 Day4冲刺
    半夜删你代码队 Day3冲刺
    Scrum 冲刺博客集合
    团队项目6——复审与事后分析
    Alpha阶段项目复审
    事后Postmortem会议
    团队作业5-测试与发布
    Scrum 冲刺第七天
  • 原文地址:https://www.cnblogs.com/crackpotisback/p/4676293.html
Copyright © 2011-2022 走看看