题意:给定一个环形道路长度为L,以及环形道路下标为0处为起始点,在环形道路上距离起始点xi位置种植一颗苹果树,该树有a个苹果,篮子的最大容量为k,那么求摘完全部苹果所需的最短距离。
思路:分析这道题发现,如果走半圈以内就可以取k个就不要走一圈,一直先取到里0点最远的剩余时,分析如果左右半圈都小于k时比较是分别走还是一圈走下来的情况,就是一种贪心,但还要讨论最后的情况。。。还是看代码的解释吧
#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<stack>
#include<math.h>
#include<string>
#include<vector>
#include<cstdio>
#include<time.h>
#include<cstring>
#include<iomanip>
#include<iostream>
#include<string.h>
#include<algorithm>
#define ll long long
#define PI acos(-1.0)
using namespace std;
ll L,n,k;
vector<ll>l,r;
struct node
{
ll pos,ge;
}a[100005];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%lld%lld%lld",&L,&n,&k);
l.clear();
r.clear();
l.push_back(0);//先放入0,方便后面
r.push_back(0);
for(int i=1;i<=n;i++)
{
scanf("%lld%lld",&a[i].pos,&a[i].ge);
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=a[i].ge;j++)
{
if(a[i].pos*2<L) l.push_back(a[i].pos);//左右半圈分别放入其中,且离散化处理
else r.push_back(L-a[i].pos);
}
}
sort(l.begin(),l.end());
sort(r.begin(),r.end());
ll e=l.size()-1,t=r.size()-1;
for(int i=k;i<l.size();i++) l[i]+=l[i-k];//当i<k是花费就是l[i],大于k时就要叠加后边新的k
for(int i=k;i<r.size();i++) r[i]+=r[i-k];
ll ans=(l[e]+r[t])*2;//不走整一圈的情况
for(ll x=0;x<=k&&x<=e+1;x++)//当左半圈剩余x,有半圈剩余k-x时,找最小值
{
ll p=e-x;
ll q=max((ll)0,t-(k-x));
ans=min(ans,(l[p]+r[q])*2+L);
}
cout<<ans<<endl;
}
}