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

 

posted @ 2015-07-25 17:49  狂徒归来  阅读(221)  评论(0编辑  收藏  举报