题意:一个渡河问题,船每次最多可以载n辆车,单程渡河的时间是t,有m辆车要渡河,问最少时间把所有车运过河去的时间是多少,这个情况下,最少的运输次数是多少。
分析:确实是动态规划,惭愧我想了很久,也没想出状态转移方程,主要是因为我一直想把过河时间和次数放在一起表示状态,其实,过河时间做状态就行了,也必须只用过河时间做状态,因为要求的是过河时间的最小值。
dp[i]表示第i辆车通过河的最小时间, trip[i]运送第i两车过河的总运输次数
状态转移方程:
dp[i] = min{ max(dp[j]+t, time[i]) + t)}, i-n <= j < i
trip[i] = trip[j] + 1, j为最小的那个
代码:
代码
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
#define MY_MAX 1500
int main(){
// freopen("in", "r", stdin);
int dp[MY_MAX], trip[MY_MAX], time[MY_MAX];
int case_num, i, j, n, t, m;
scanf("%d", &case_num);
while(case_num--){
memset(dp, 0xFF, sizeof(dp));
memset(trip, 0, sizeof(trip));
scanf("%d %d %d", &n, &t, &m);
for(i=1; i<=m; ++i)
scanf("%d", &time[i]);
dp[0] = -t;
dp[1] = time[1] + t;
trip[1] = 1;
for(i=2; i<=m; ++i){
for(j=max(0, i-n); j<i; ++j){
int tmp = max(dp[j]+t, time[i]) + t;
if(dp[i] == -1){
dp[i] = tmp;
trip[i] = trip[j] + 1;
continue;
}
if(tmp < dp[i]){
dp[i] = tmp;
trip[i] = trip[j] + 1;
}
else if(tmp == dp[i] && trip[j] + 1 < trip[j])
trip[i] = trip[j] + 1;
}
}
printf("%d %d\n", dp[m], trip[m]);
}
return 0;
}