一个长为l的圆上种了n棵苹果树,每棵苹果树上有a[i]个苹果,有一个篮子最多能装k个苹果。将所有的苹果都摘回来最短距离为多少。
思路:
化整为零,将苹果树转化为一个个的苹果,贪心,从两边分别考虑摘苹果装在篮子里。要么直接放满了篮子走回来,要么摘着苹果转一圈回来,找二者的较小值。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=100010;
int cnt,num[N],num_l[N],num_r[N];
ll dis_l[N],dis_r[N];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int l,n,k,p,x,i,j,cnt=0;
scanf("%d%d%d",&l,&n,&k);
for(i=1;i<=n;i++)
{
scanf("%d%d",&p,&x);
for(j=1;j<=x;j++)
num[++cnt]=p;
}
int lnum=0,rnum=0;
for(i=1;i<=cnt;i++)
{
if(num[i]*2<l)
num_l[++lnum]=num[i];
else
num_r[++rnum]=l-num[i];
}
sort(num_l+1,num_l+lnum+1);
sort(num_r+1,num_r+rnum+1);
for(i=1;i<=lnum;i++)
{
dis_l[i]=(i<=k)?num_l[i]:dis_l[i-k]+num_l[i];
}
for(i=1;i<=rnum;i++)
{
dis_r[i]=(i<=k)?num_r[i]:dis_r[i-k]+num_r[i];
}
ll sum=(dis_l[lnum]+dis_r[rnum])*2;
for(i=0;i<=k;i++)
{
if(i>lnum)
break;
int ll=lnum-i;
int rr=max(0,rnum-(k-i));
sum=min(sum,(dis_l[ll]+dis_r[rr])*2+l);
}
printf("%lld\n",sum);
}
return 0;
}