Mortal Kombat Tower(dp)

Mortal Kombat Tower

题意

有两个人闯关,第一个人先走,第二个人再走。每人最少走一步,最多走两步。给定一个01数组,当值为1的时候,第一个人需花费1块钱才可以走,否则不用花钱。第二个人随便走,不用花钱。问最少花费多少金币。

数据范围

线性

思路

显然是状态机dp。 f [ i ] [ 0 / 1 ] f[i][0/1] f[i][0/1]表示走了前 i i i步,并且最后一步是 0 / 1 0/1 0/1走的方案中的花费最小值。状态转移方程为:
f ( i , 0 ) = m i n ( f ( i − 1 , 1 ) + a [ i ] , f ( i − 2 , 1 ) + a [ i ] + a [ i − 1 ] ) f(i,0) = min(f(i-1,1) + a[i], f(i-2,1) + a[i] + a[i-1]) f(i,0)=min(f(i1,1)+a[i],f(i2,1)+a[i]+a[i1])
f ( i , 1 ) = m i n ( f ( i − 1 , 0 ) , f ( i − 2 , 0 ) ) f(i,1) = min(f(i-1,0), f(i-2,0)) f(i,1)=min(f(i1,0),f(i2,0))
其中要先将f数组初始化为正无穷, f ( 1 , 0 ) = a [ 1 ] , f ( 2 , 0 ) = a [ 1 ] + a [ 2 ] f(1,0) = a[1], f(2,0) = a[1] + a[2] f(1,0)=a[1],f(2,0)=a[1]+a[2]

代码

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

const int N = 200010, inf = 0x3f3f3f3f;

int n;
int a[N];
int f[N][2];

int main()
{
    
    
    int T;
    cin >> T;
    while(T--){
    
    
        cin >> n;
        memset(f,0x3f,sizeof(f));
        for(int i=1;i<=n;i++) cin >> a[i];
        f[1][0] = a[1];
        f[2][0] = a[1] + a[2];
        for(int i=2;i<=n;i++){
    
    
            f[i][0] = min(f[i][0], min(f[i-1][1] + a[i], f[i-2][1] + a[i] + a[i-1]));
            f[i][1] = min(f[i][1], min(f[i-1][0], f[i-2][0]));
        }
        cout << min(f[n][0], f[n][1]) << endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43634220/article/details/108614878
今日推荐