打怪——dp

题目思路:

dp[i][j][k]代表打到第i个怪物使用了第j种武器第k种属性,注意间接转化可能花的时间更少,所以要用弗洛伊德求武器和属性转化的最短路,然后在dp时武器和属性的状态转移要分开,不然会超时
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll a,b,c,n,ans;// a is weapon, b is attribute, c is kind of monster, n is number of monster, ans is the answer
ll dp[101][101][101];
ll x[101],y[101];// Time required to start using weapons and attributes
ll f[101][101],g[101][101];// change time of weapons and attributes
ll h[21][101][101]; // the impair of monster 
ll w[101],t[101]; // the blood and class of monster
// *************maybe need use long long or double********************
void solve();
int main()
{
    //输入 
    scanf("%lld%lld%lld%lld",&a,&b,&c,&n);
    for(int i = 1;i<=a;i++)
        scanf("%lld",&x[i]);
    for(int i = 1;i<=b;i++)
        scanf("%lld",&y[i]);    
    for(int i = 1;i<=a;i++)
        for(int j = 1;j<=a;j++)
            scanf("%lld",&f[i][j]);
    for(int i = 1;i<=b;i++)
        for(int j = 1;j<=b;j++)
            scanf("%lld",&g[i][j]);
    for(int i = 1;i<=c;i++)
        for(int j = 1;j<=a;j++)
            for(int k = 1;k<=b;k++)
                scanf("%lld",&h[i][j][k]);
    for(int i = 1;i<=n;i++)
        scanf("%lld",&w[i]);
    for(int i = 1;i<=n;i++)
        scanf("%lld",&t[i]);    
    solve();
    printf("%lld",ans);
    return 0;
}
void solve()
{
    //间接转化可能时间更短 ,所以求最短路 
    for(int k=1; k<=a; k++)
        for(int i=1; i<=a; i++)
            for(int j=1; j<=a; j++) 
                f[i][j] = min(f[i][j],f[i][k]+f[k][j]);
 
    for(int k=1; k<=b; k++)
        for(int i=1; i<=b; i++)
            for(int j=1; j<=b; j++) 
                g[i][j] = min(g[i][j],g[i][k]+g[k][j]);
    //初始化
    memset(dp,0x3f,sizeof(dp));
    for(int i=1; i<=a; i++)
        for(int j=1; j<=b; j++) 
            dp[0][i][j]=x[i]+y[j];
    //dp代表打到第i个怪物使用了第j种武器第k种属性 ,武器属性分开加 
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=a; j++)
            for(int k=1; k<=b; k++)
                for(int p=1; p<=a; p++) 
                    dp[i][j][k] = min(dp[i][j][k],dp[i-1][p][k]+f[p][j]);
        for(int j=1; j<=a; j++)
            for(int k=1; k<=b; k++)
                for(int p=1; p<=b; p++) 
                    dp[i][j][k] = min(dp[i][j][k],dp[i][j][p]+g[p][k]);
        for(int j=1; j<=a; j++)
            for(int k=1; k<=b; k++) 
                dp[i][j][k]+=w[i]/h[t[i]][j][k]+(w[i]%h[t[i]][j][k]!=0);
    }
    ans = 1e18;//不能0x3f3f3f3f 
    for(int i = 1;i<=a;i++)
        for(int j = 1;j<=b;j++)
            ans = min(ans,dp[n][i][j]);
}

猜你喜欢

转载自www.cnblogs.com/loganacmer/p/12233085.html