• 解题报告 之 HDU5303 Delicious Apples


    解题报告 之 HDU5303 Delicious Apples


    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

    题目大意:一个给定长度为L的圈。你在0位置。

    圈上有n个苹果树(给出位置),每棵树下有一定数量的苹果。你有一个能装K个苹果的框子。如今你要将全部苹果运到你所在的位置。问你最少走多少路?


    分析:第一点非常easy想到,离起点左右非常近的苹果更倾向于选择原路返回更省。而靠近中间的苹果有可能打包绕一圈再回来更省。

    那么问题来了?这个“中间”究竟如何才算中间呢,这个点就是这个题的精髓。

    大家能够把这个中间想成一个区间,问题的难点就转化为了怎么选择这个区间。也就是我们要决定选择哪些苹果绕一圈打包回来更省。


    这的确是一个难解决的问题。。也是本题巧妙的地方。我们枚举究竟要把那些苹果绕一圈打包带回。我们把一个一个苹果离散出来而不再以苹果树作为考虑对象。并把这些苹果划分为更靠近左边和更靠近右边的。那么我们要枚举的就是,要从左边拿多少个(无疑是最远的那几个)到绕一圈的这个框中。

    注意重点在于,从左边最多取K个,也就是仅仅有最后一筐可能须要绕一圈。由于假设从左边取超过K个。那么我们全然能够先取K个依照原路返回的方法(路程一定<=L),那之后问题终于回归不超过K个。


    我们枚举的实质事实上在尝试一种平衡局面,使得左右两边选择原路返回路线的框能够尽量利用充分,而不要出现有一趟原路返回仅仅装1、2个苹果。

    上代码:
    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<vector>
    #include<cstring>
    
    using namespace std;
    typedef long long ll;
    
    const int MAXN = 1e5 + 10;
    ll loc[MAXN];
    ll disl[MAXN], disr[MAXN];//依照原路返回策略取完第i个苹果所走的路程
    ll ans, L, n, k, cnt;
    vector<ll> lloc, rloc; //存储从左右数的苹果位置
    
    int main()
    {
    	int kase;
    	scanf( "%d", &kase );
    	while(kase--)
    	{
    		memset( disl, 0, sizeof disl );
    		memset( disr, 0, sizeof disr );
    		lloc.clear();
    		rloc.clear();
    		cnt = 0;
    
    		scanf( "%lld%lld%lld", &L, &n, &k );
    		for(int i = 1; i <= n; i++)
    		{
    			ll location, number;
    			scanf( "%lld%lld", &location, &number );
    			for(int j = 1; j <= number; j++) //离散化
    				loc[cnt++] = location;
    			
    		}
    
    		for(int i = 0; i < cnt; i++)
    		{
    			if(2 * loc[i] < L)
    				lloc.push_back( loc[i] );
    			else
    				rloc.push_back( L - loc[i] );
    		}//苹果分边
    
    		sort( lloc.begin(), lloc.end() );
    		sort( rloc.begin(), rloc.end() );
    
    		int left = lloc.size(), right = rloc.size();
    
    		for(int i = 0; i < left; i++)
    			disl[i + 1] = (i + 1 <= k ? lloc[i] : disl[i + 1 - k] + lloc[i]);
    		for(int i = 0; i < right; i++)
    			disr[i + 1] = (i + 1 <= k ? rloc[i] : disr[i + 1 - k] + rloc[i]);
    
    		ans = (disl[left] + disr[right]) * 2; //不绕一圈的情况,不要忘了
    
    		for(int i = 0; i <= left&&i <= k; i++)//枚举绕一圈的那框从左边取多少
    		{
    			ll pickl = left - i;
    			ll pickr = right - (k - i);
    
    			ans = min( ans, 2 * (disl[pickl] + disr[pickr]) + L );
    		}
    
    		printf( "%lld
    ", ans );
    	}
    	return 0;
    }




  • 相关阅读:
    03_02_leetcode_24_删除有序数组的重复项
    03_02_leetcode_141_环形链表
    03_02_leetcode_24_两两交换链表中的结点
    Solution -「ZJOI 2014」力
    Solution -「GXOI / GZOI 2019」宝牌一大堆
    Solution -「CSP 2019」Centroid
    Solution -「CSP 2019」Partition
    Note -「Suffix Automaton」SAM
    Solution -「BalticOI 2004」Sequence
    Solution -「BZOJ 3779」重组病毒
  • 原文地址:https://www.cnblogs.com/liguangsunls/p/7210761.html
Copyright © 2020-2023  润新知