题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5303
题意:在一个长为L的环形路径上种着一些苹果树,告诉你苹果树的位置(题目中以0~L指示坐标)及苹果树上的苹果数,现在你要采集所有的苹果(大概是你有一个容量为K的筐,你采集的苹果要装在筐里,采集完要回到坐标0的家里清空筐),问你最少需要走多少路
解:可以想象最多需要走一次整环,剩下的是走两个半环,那么分别对两个半环贪心(由于数据量较小,有很优雅的姿势~)
然后考虑走的这一次整环,由于这次整环的花费是固定的(L),那么能代替之前花费越高的(K个)越好,需要枚举这K个里面有多少个是左边的,剩下的是右边的
1 /* 2 * Problem: hdu5303 Delicious Apples 3 * Author: SHJWUDP 4 * Created Time: 2015/8/10 星期一 21:46:10 5 * File Name: 1006.cpp 6 * State: Accepted 7 * Memo: 贪心+枚举 8 */ 9 #include <iostream> 10 #include <cstdio> 11 #include <vector> 12 #include <cstring> 13 #include <algorithm> 14 15 using namespace std; 16 17 int L, n, K; 18 vector<long long> fl, fr;//f[i]:取得前i个苹果的最小花费 19 int main() { 20 #ifndef ONLINE_JUDGE 21 freopen("in", "r", stdin); 22 //freopen("out", "w", stdout); 23 #endif 24 int T; 25 scanf("%d", &T); 26 while(T--) { 27 scanf("%d%d%d", &L, &n, &K); 28 fl.clear(); fr.clear(); 29 fl.push_back(0); //强制使得fl[0]=0; 30 fr.push_back(0); //强制使得fr[0]=0; 31 for(int i=0; i<n; i++) { 32 int a, b; 33 scanf("%d%d", &a, &b); 34 while(b--) { 35 if(a*2<L) fl.push_back(a); 36 else fr.push_back(L-a); 37 } 38 } 39 sort(fl.begin(), fl.end()); 40 sort(fr.begin(), fr.end()); 41 for(int i=K; i<(int)fl.size(); i++) fl[i]+=fl[i-K]; 42 for(int i=K; i<(int)fr.size(); i++) fr[i]+=fr[i-K]; 43 long long ans=(fl.back()+fr.back())<<1; 44 for(int x=0; x<=K; x++) { //在左边还剩下x个,右边剩下K-x个苹果时走整圈 45 int a=max(0, (int)fl.size()-1-x); 46 int b=max(0, (int)fr.size()-1-(K-x)); 47 long long tmp=(fl[a]+fr[b])<<1; 48 ans=min(ans, L+tmp); 49 } 50 printf("%I64d\n", ans); 51 } 52 return 0; 53 }