設f(i,j)表示第i次運輸能將第j輛車運到對岸,抵達時所花的最小時間。
f(i,j)=f(i-1,j-k)+回岸的時間T+T。當然,若回岸時車還未到達,f(i,j)=j車抵達的時間+T。
#include <string>
#define min( x, y ) ( x < y ? x : y )
#define max( x, y ) ( x > y ? x : y )
int T, N, M, CS;
int t[1500];
int b[2][1500]; // 第n次渡過m人最小時間,滾存
void init ()
{
scanf ( "%d%d%d", &N, &T, &M );
int i;
for ( i = 1; i <= M; i ++ )
scanf ( "%d", &t[i] );
}
void dp ()
{
int i, j, k, p;
int minTime = 1 << 30, minStep, step;
memset ( b, 64, sizeof ( b ) );
for ( j = 1, p = 0, step = 1; j <= N; j ++ )
{
b[p][j] = T + t[j];
if ( j == M && b[p][j] < minTime )
minTime = b[p][j], minStep = step;
}
//pt ( p );
for ( i = 2, p = 1 - p, step ++; i <= M; i ++, p = 1 - p, step ++ )
{
memset ( b[p], 64, sizeof ( b[p] ) );
for ( j = i; j <= min ( M, i * N ); j ++ )
{
for ( k = 1; k <= N; k ++ )
b[p][j] = min ( b[p][j], max ( b[1 - p][j - k] + T, t[j] ) + T );
if ( j == M && b[p][j] < minTime )
minTime = b[p][j], minStep = step;
}
//pt ( p );
}
printf ( "%d %d ", minTime, minStep );
}
int main ()
{
//freopen ( "in.txt", "r", stdin );
//freopen ( "out.txt", "w", stdout );
scanf ( "%d", &CS );
int i;
for ( i = 0; i < CS; i ++ )
{
init ();
dp ();
}
return 0;
}