链接:点击打开链接
题意:有一个长为L的环,n个苹果树,一个篮子最多装k个苹果,装满后要回到起点重新出发,给出n个苹果树顺时针的位置及苹果的个数,求摘完所有苹果走的最小路程
代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>
using namespace std;
const long long INF=0x3f3f3f3f3f3f3f3f;
struct node{
long long x,y;
friend bool operator<(node a,node b){
return a.x<b.x;
}
}s[100005];
long long dp[2][100005];
int main(){ //dp[0][j]表示顺时针拿j个苹果返回起点的最短距离
long long t,i,j,l,n,k,ans,num,sum; dp[1][j]表示逆时针拿j个苹果返回起点的最短距离
scanf("%I64d",&t);
while(t--){
scanf("%I64d%I64d%I64d",&l,&n,&k);
memset(dp,0,sizeof(dp));
sum=0;
for(i=1;i<=n;i++){
scanf("%I64d%I64d",&s[i].x,&s[i].y);
sum+=s[i].y;
}
sort(s+1,s+n+1); //按位置排序
num=1;
for(i=1;i<=n;i++){
for(j=1;j<=s[i].y;j++){
if(num>k){ //判断是否大于k和是原路返回近还是绕圈近
if(2*s[i].x<l)
dp[0][num]=dp[0][num-k]+2*s[i].x;
else
dp[0][num]=dp[0][num-k]+l;
}
else{
if(2*s[i].x<l)
dp[0][num]=dp[0][0]+2*s[i].x;
else
dp[0][num]=dp[0][0]+l;
}
num++;
}
}
num=1;
for(i=n;i>=1;i--){
for(j=1;j<=s[i].y;j++){
if(num>k){
if(2*(l-s[i].x)<l)
dp[1][num]=dp[1][num-k]+2*(l-s[i].x);
else
dp[1][num]=dp[1][num-k]+l;
}
else{
if(2*(l-s[i].x)<l)
dp[1][num]=dp[1][0]+2*(l-s[i].x);
else
dp[1][num]=dp[1][0]+l;
}
num++;
}
}
ans=INF;
for(i=0;i<=sum;i++)
ans=min(ans,dp[0][i]+dp[1][sum-i]);
printf("%I64d\n",ans);
}
return 0;
}