zoj 3017 Extreme Gameplay

http://acm.hust.edu.cn:8080/judge/contest/view.action?cid=11975#problem/D

用f【i】【j】表示i号城堡到j号城堡所需要的魔法值。

首先要用floyd算出任意两个城市之间到达所需要的最小魔法值。

然后用t【i】【j】表示i号城堡从j-1号房间到达j号房间所需要的时间。

用dp【k】【i】【j】表示当前魔法值为k到达i号城堡j号房间所需要的最短时间。

如果已经知道了dp【k】【i】【j】那么我们就可以推出dp【k】【i】【j+1】,也可以推出dp【temp】【l】【j+1】(其中l是另一个城堡,temp是当期魔法值减去i号

城堡到j号城堡所需要的魔法值。其中l!=i我们需要枚举l。

本题

#include<iostream>

#include<string.h>

#include<algorithm>

#include<stdio.h>

#define inf 0x7fffffff

using namespace std;

int dp[150][20][150];

int f[20][20];

int t[20][150];

int main()

{

   int test;

   int n,m,z;

   cin>>test;

   for(int p=1;p<=test;p++)

   {

       cin>>n>>m>>z;

       for(int i=1;i<=m;i++)

           for(int j=2;j<=n;j++)

               cin>>t[i][j];

       for(int i=1;i<=m;i++)

           for(int j=1;j<=m;j++)

               cin>>f[i][j];

       for(int k=1;k<=m;k++)

           for(int i=1;i<=m;i++)

               for(int j=1;j<=m;j++)

                   if(i!=j)

                       f[i][j]=min(f[i][j],f[i][k]+f[k][j]);

       memset(dp,-1,sizeof(dp));

       dp[z][1][1]=0;

       for(int i=2;i<=m;i++)

       {

           int temp=z-f[1][i];

           if(temp>=0)

           {

               dp[temp][i][1]=0;

           }

       }

       for(int j=1;j<n;j++)

       {

           for(int k=0;k<=z;k++)

           {

               for(int i=1;i<=m;i++)

               if(dp[k][i][j]!=-1)

               {

                   if(dp[k][i][j+1]==-1||dp[k][i][j+1]>dp[k][i][j]+t[i][j+1])

                       dp[k][i][j+1]=dp[k][i][j]+t[i][j+1];

                   for(int l=1;l<=m;l++)

                       if(l!=i)

                       {

                           int temp=k-f[i][l];

                           if(temp>=0)

                           {

                               int ans=dp[k][i][j]+t[l][j+1];

                               if(dp[temp][l][j+1]==-1||dp[temp][l][j+1]>ans)

                                   dp[temp][l][j+1]=ans;

                           }

                       }

               }

           }

       }

       int ans=inf;

       for(int i=1;i<=m;i++)

           for(int k=0;k<=z;k++)

           if(dp[k][i][n]!=-1)

               ans=min(ans,dp[k][i][n]);

       cout<<ans<<endl;

   }

   return 0;

}

 

是属于那种知道当前状态去递推后一种状态的情况。

你可能感兴趣的:(game)