zoj 3017 - Extreme Gameplay

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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值