题意:
摆渡:每次可以摆渡n辆车,摆渡要来回的,去和返的时间一样都是t,有m辆车需要摆渡。
这m辆车抵达码头的时间给定。
问如果摆渡,可以使摆渡完所有的车的时间最少。
且输出这个条件下,最少的来回数。
思路:
贪心+dp。
现在要满足总时间最少,则最晚抵达的车要尽早摆渡过岸。
假设最晚抵达的车,车号为m的时间为 40。
则最后一趟摆渡出发的时间可以是t>=40的区间都可以.但是当然 t 越小越好。
先进行一下贪心:
因为每次摆渡可以运n辆车,则最后一车的时候还可以一起顺带n-1辆车。
怎么选这n-1辆车呢?显然是m-1,m-2...m-n+1一起。
因为越后面的车辆,摆渡的时间容许度越苛刻。如果
m-2,10.
m-1,30.
m,40.
对于m-2可以在>=10的时间内摆渡,m-1可以在>=30的时间内摆渡。
m-1的摆渡时间 真包含于 m-2的摆渡时间。
所以将m-1顺带带走显然比带走m-2的车更佳,起码不会更坏。
然后是dp的转移方程:
dp[i]=Max(dp[i-n]+2*t,a[i]);
注意就是这里dp[i]的i是从m开始,i=m,i=m-n,i=m-2*n....按每n个车作为一个集合来处理的。
最后一个集合有可能不足n辆车。
因为m%n不一定等于0.
先写的上面这些思路,再写的下面的代码。
一次AC,没啥陷阱。
#include<iostream>
#include<vector>
#include<string>
#include<queue>
#include<cmath>
#include<algorithm>
#define llong long long
#define Min(a,b) (a<b?a:b)
#define Max(a,b) (a>b?a:b)
#define Abs(a) ((a)>0?(a):-(a))
#define Mod(a,b) (((a)-1+(b))%(b)+1)
using namespace std;
int n,m,t;
const int N=1505;
const int M=105;
const int inf=2099999999;
int a[N];
int dp[N];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
memset(dp,0,sizeof(dp));
scanf("%d%d%d",&n,&t,&m);
for(int i=1;i<=m;i++)
scanf("%d",a+i);
int now=m%n,count=1;
if(!now)
{
now=n;
}
dp[now]=a[now];
now+=n;
while(now<=m)
{
count++;
dp[now]=Max(dp[now-n]+2*t,a[now]);
now+=n;
}
printf("%d %d\n",dp[m]+t,count);
}
return 0;
}