zoj 3017 - Extreme Gameplay

来源:互联网 发布:明解c语言 pdf 高清版 编辑:程序博客网 时间:2024/06/10 15:41

题目:有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 1000000001int 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;}


0 0