題意:一個長爲L的圈種上n顆樹,每棵樹的座標爲xi,結了ai個蘋果,用大小爲k的籃子把所有蘋果裝回來,問最少走多少路
解一:被神奇的dp教做人了
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define ll __int64
#define MIN(a,b) ((a)<(b)?(a):(b))
const int maxn=100005;
using namespace std;
ll dp[3][maxn];
struct aaa
{
int x,a;
}tree[maxn];
int cmp(aaa a,aaa b)
{
return a.x<b.x;
}
int main()
{
int t;
int l,n,k;
while(scanf("%d",&t)!=-1)
{
while(t--)
{
scanf("%d%d%d",&l,&n,&k);
for(int i=0;i<n;i++)
scanf("%d%d",&tree[i].x,&tree[i].a);
sort(tree,tree+n,cmp);
dp[0][0]=dp[1][0]=0;
int fr,ed=1;
for(int i=0;i<n;i++) //順時針每個蘋果取到時走的路
{
for(int j=0;j<tree[i].a;j++)
{
fr=ed-k>0?ed-k:0;
dp[0][ed]=dp[0][fr]+(2*tree[i].x>l?l:2*tree[i].x);
ed++;
}
}
ed=1;
ll sum=0;
for(int i=n-1;i>=0;i--) //逆時針每個蘋果取到時走的路
{
sum+=tree[i].a;
for(int j=0;j<tree[i].a;j++)
{
fr=ed-k>0?ed-k:0;
dp[1][ed]=dp[1][fr]+(2*(l-tree[i].x)>l?l:2*(l-tree[i].x));
ed++;
}
}
ll lenth=1000000000;
for(ll i=0;i<=sum;i++)
lenth=MIN(lenth,dp[0][i]+dp[1][sum-i]); //找最小的
printf("%I64d\n",lenth);
}
}
return 0;
}
解二:神奇的貪心,分成兩個半圓,左右分別貪到k一下,最後再貪一圈,不過左右貪心從最遠的樹開始貪