最近我发现cf上出现很多状态机模型,然而这种模型是dp中最容易理解也是最有套路的一点
本题能用这种方法做的原因是数值都是大于0的,就不可能存在先走上去再走下来的情况,我刚开始误认为有这种情况导致无法下手
我们显然可以定义f[i][j]表示用j工具到达i层的最小值,因此j有两个选项,如果对于本题一开始没有看出来的,我们可以从数据范围入手
题目的n已经给了10^5范围,而这个n维度是不可能省略的,所以我们想到第二维不可能开很大,自然会想到用状态机表示工具
状态机最重要的初始状态,我们定义f[1][0]=0,f[1][1]=c
因为我们定义的状态是用j工具到达i层,又是从1出发,所以0处不用,而1处需要加上初始等电梯的时间,以便于后期转移
注意本题的ab数组表示的是i到i+1所需的时间,所以我们转移时应该用i-1的数据转移
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> #include<map> #include<set> #include<vector> using namespace std; typedef long long ll; const int N=5e5+10; const int inf=0x3f3f3f3f; int f[N][2];//到i层以及用j工具需要的最小值 int a[N]; int b[N]; int main(){ int i; int n; int c; cin>>n>>c; for(i=1;i<=n-1;i++){ scanf("%d",&a[i]); } for(i=1;i<=n-1;i++){ scanf("%d",&b[i]); } memset(f,0,sizeof f); f[1][0]=0; f[1][1]=c; cout<<0<<" "; for(i=2;i<=n;i++){ f[i][0]=min(f[i-1][0]+a[i-1],f[i-1][1]+a[i-1]); f[i][1]=min(f[i-1][0]+b[i-1]+c,f[i-1][1]+b[i-1]); cout<<min(f[i][0],f[i][1])<<" "; } cout<<endl; return 0; }