题目:有M个城堡,每个城堡有N的连续的房间,每次可以消耗魔法在不同城堡的同一编号的房间中瞬移,
或者消耗一定的时间走向本城堡的下一个地点,
求从1号城堡1号房间出发,到达任意第N个房间的最小时间。
分析:dp,最短路,背包(01比较省蓝)。每次决策分两步进行,使用魔法和直接走。
状态:f(i,j,k)魔法为k时走到编号j城堡,编号i的房间,的最小时间;
阶段:很明显,当前的房间编号;
决策:相同编号房间不同城堡之间的跳转(魔法);相同城堡连续编号的跳转(走路);
初始化:利用 floyd计算统一编号城堡间的最小传送代价;
时间: T = O(NZM^2)。
说明:把数组的行列写反了。调了好几个小时。囧。(2011-9-23 03:26)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define Max 1000000001
int mcost[ 11 ][ 11 ];
int tcost[ 11 ][ 101 ];
int F[ 101 ][ 11 ][ 101 ];
int main()
{
int T,N,M,Z;
scanf("%d",&T);
for ( int t = 1 ; t <= T ; ++ t ) {
scanf("%d%d%d",&N,&M,&Z);
for ( int i = 1 ; i <= M ; ++ i )
for ( int j = 2 ; j <= N ; ++ j )
scanf("%d",&tcost[ i ][ j ]);
for ( int i = 1 ; i <= M ; ++ i )
for ( int j = 1 ; j <= M ; ++ j )
scanf("%d",&mcost[ i ][ j ]);
for ( int k = 1 ; k <= M ; ++ k )
for ( int i = 1 ; i <= M ; ++ i )
for ( int j = 1 ; j <= M ; ++ j )
if ( mcost[ i ][ j ] > mcost[ i ][ k ] + mcost[ k ][ j ] )
mcost[ i ][ j ] = mcost[ i ][ k ] + mcost[ k ][ j ];
for ( int i = 1 ; i <= N ; ++ i )
for ( int j = 1 ; j <= M ; ++ j )
for ( int k = 0 ; k <= Z ; ++ k )
F[ i ][ j ][ k ] = Max;
F[ 1 ][ 1 ][ Z ] = 0;
for ( int i = 2 ; i <= N ; ++ i ) {
for ( int j = 1 ; j <= M ; ++ j )
for ( int l = 1 ; l <= M ; ++ l )
for ( int k = mcost[ j ][ l ] ; k <= Z ; ++ k )
if ( F[ i-1 ][ l ][ k-mcost[ j ][ l ] ] > F[ i-1 ][ j ][ k ] )
F[ i-1 ][ l ][ k-mcost[ j ][ l ] ] = F[ i-1 ][ j ][ k ];
for ( int j = 1 ; j <= M ; ++ j )
for ( int k = 0 ; k <= Z ; ++ k )
if ( F[ i-1 ][ j ][ k ] != Max )
F[ i ][ j ][ k ] = F[ i-1 ][ j ][ k ] + tcost[ j ][ i ];
}
int Min = Max;
for ( int j = 1 ; j <= M ; ++ j )
for ( int k = 0 ; k <= Z ; ++ k )
if ( Min > F[ N ][ j ][ k ] )
Min = F[ N ][ j ][ k ];
printf("%d\n",Min);
}
return 0;
}