您的位置:首页 > 移动开发

oldssoj2674Delicious Apples(离散+贪心+环上折半dp)

2015-08-25 20:55 357 查看

题目描述

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 x­i, 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?

1≤n,k≤105,ai≥1,a1+a2+...+an≤105

1≤L≤109

0≤x[i]≤L

There are less than 20 huge testcases, and less than 500 small testcases.

输入

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 total distance in a line for each testcase.

样例输入

210 3 22 28 25 110 4 12 28 25 10 10000

样例输出

1826

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#define ll long long
using namespace std;
const int maxn=100005;
int n,len,k;
ll dpl[maxn],dpr[maxn],posl[maxn],posr[maxn],l,r,ans;
inline int get(){
char c;while(!isdigit(c=getchar()));
int v=c-48;while(isdigit(c=getchar()))v=v*10+c-48;
return v;
}
int main(){
int t=get();
while(t--){
memset(dpl,0,sizeof(dpl));
memset(dpr,0,sizeof(dpr));
memset(posl,0,sizeof(posl));
memset(posr,0,sizeof(posr));
len=get();n=get();k=get();
l=0;r=0;
for(int i=1;i<=n;++i){
int pos,num;
pos=get();num=get();
if((pos<<1)<=len)while(num--)posl[++l]=pos;   //把左边的苹果离散
else while(num--)posr[++r]=len-pos;           //把右边的苹果离散
}
sort(posl+1,posl+1+l);
sort(posr+1,posr+1+r);
for(int i=1;i<=l;++i){
if(i<=k)dpl[i]=posl[i];else dpl[i]=dpl[i-k]+posl[i];      //取前i个的最短路程和
}
for(int i=1;i<=r;++i){
if(i<=k)dpr[i]=posr[i];else dpr[i]=dpr[i-k]+posr[i];
}
ans=(dpl[l]+dpr[r])<<1;
for(int i=1;i<=l && i<=k;++i){
ll Le=l-i,Ri=r-k+i;
ans=min(ans,((dpl[Le]+dpr[Ri])<<1)+len);
}
printf("%lld\n",ans);
}
return 0;
}


思路:取苹果的路径有两种,一种是原路返回,一种是绕一圈。什么时候要绕一圈是本题的关键。我们发现,如果一边能放满篮子,原路返回较优,而绕一圈,是在左右剩下不到k个苹果时,为了避免只拿一点苹果回去造成的浪费。容易发现,绕最多只绕一圈。而绕的这一圈从左侧的尾部和右侧的尾部拿多少是可以枚举的。原路返回可以dp来找最短。取二者的min即可。

评价:思想很巧妙。离散的处理
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: