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

hdu5303(15年多校集训第二轮1004题delicious apple)

2015-07-27 11:20 387 查看
题目大意:有一个长度为l环路上边有坐标,你有个容量为k的篮子,你的房子位于坐标0点,其他坐标处有n棵苹果树,告诉你苹果树的位置和苹果树上的苹果的数目,问你取完所有苹果的最短路程。

解题思路:一开始没做出来,看了学车中学的题解,恍然大悟。首先,把环路剖开来看,这样就有两个半边了,分别对两个半边进行贪心(先拿最远的),又因为它是个环路,可以走一圈,所以在找下走一圈的情况;

#include<cstdio>

#include<cstring>

#include<algorithm>

#include<iostream>

using namespace std;

const int maxn=2000000+10000;

typedef long long LL;

int t,l,n,k,x[maxn];

int a1[maxn],n1,a2[maxn],n2;

LL ans,su1[maxn],su2[maxn];//半边贪心的结果

int main()

{

scanf("%d",&t);

while(t--)

{

scanf("%d%d%d",&l,&n,&k);

int cnt=0;

for(int i=1; i<=n; i++)

{

int dis,num;

scanf("%d%d",&dis,&num);

for(int j=1; j<=num; j++)

x[++cnt]=dis;

}

k=min(k,cnt);

n1=n2=0;

for(int i=1; i<=cnt; i++)

{

if(x[i]*2<l) a1[++n1]=x[i];

else a2[++n2]=l-x[i];

}

sort(a1+1,a1+n1+1);

sort(a2+1,a2+n2+1);

su1[0]=su2[0]=0;

//对两个半边进行贪心

for (int i=1; i<=n1; i++)

if(i<=k)su1[i]=a1[i];

else su1[i]=a1[i]+su1[i-k];

for (int i=1; i<=n2; i++)

if(i<=k)su2[i]=a2[i];

else su2[i]=a2[i]+su2[i-k];

ans=(su1[n1]+su2[n2])*2;

//走一圈的情况

for (int i=0; i<=n1 && i<=k; i++)

{

int left=n1-i,right=max(0,n2-(k-i));//右边拿i个,左边k-i个

ans=min(ans,l+(su1[left]+su2[right])*2);

}

printf("%lld\n",ans);

}

return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: