https://codeforces.com/contest/1221/problem/D
因为每个木板只和左右考虑,那么我要跟左右都不同,就最多升高2次
设dp[i][0],dp[i][1],dp[i][2]为第i块模板升高0,1,2次的前i块不同的最小代价,每次更新都跟a[i-1]比较一下高度转移即可
这位8分钟写完的甚至用了滚动数组
#include<bits/stdc++.h>
using namespace std;
using LL=long long;
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int T;
cin>>T;
while(T--){
int n;
cin>>n;
vector<int> a(n),b(n);
for(int i=0;i<n;++i){
cin>>a[i]>>b[i];
}
LL dp[2][3]={};
dp[0][0]=0;
dp[0][1]=b[0];
dp[0][2]=2*b[0];
int cur=0;
for(int i=1;i<n;++i){
cur^=1;
for(int j=0;j<=2;++j){
dp[cur][j]=1e18;
for(int k=0;k<=2;++k){
if(a[i]+j!=a[i-1]+k){
dp[cur][j]=min(dp[cur][j],dp[cur^1][k]+j*b[i]);
}
}
}
}
cout<<min(dp[cur][0],min(dp[cur][1],dp[cur][2]))<<endl;
}
return 0;
}
但是我的转移写得及其辣鸡,强行手写不循环写,坏习惯
#include<bits/stdc++.h>
#define maxl 300010
using namespace std;
int n,m,ans;
int a[maxl],b[maxl];
long long dp[maxl][3];
char s[maxl];
inline void prework()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d%d",&a[i],&b[i]);
}
inline void mainwork()
{
for(int i=1;i<=n;i++)
{
if(a[i]==a[i-1])
dp[i][0]=min(dp[i-1][1],dp[i-1][2]);
else if(a[i]==a[i-1]+1)
dp[i][0]=min(dp[i-1][0],dp[i-1][2]);
else if(a[i]==a[i-1]+2)
dp[i][0]=min(dp[i-1][0],dp[i-1][1]);
else
dp[i][0]=min(dp[i-1][0],min(dp[i-1][1],dp[i-1][2]));
if(a[i]+1==a[i-1])
dp[i][1]=min(dp[i-1][1],dp[i-1][2])+b[i];
else if(a[i]+1==a[i-1]+1)
dp[i][1]=min(dp[i-1][0],dp[i-1][2])+b[i];
else if(a[i]+1==a[i-1]+2)
dp[i][1]=min(dp[i-1][0],dp[i-1][1])+b[i];
else
dp[i][1]=min(dp[i-1][0],min(dp[i-1][1],dp[i-1][2]))+b[i];
if(a[i]+2==a[i-1])
dp[i][2]=min(dp[i-1][1],dp[i-1][2])+2*b[i];
else if(a[i]+2==a[i-1]+1)
dp[i][2]=min(dp[i-1][0],dp[i-1][2])+2*b[i];
else if(a[i]+2==a[i-1]+2)
dp[i][2]=min(dp[i-1][0],dp[i-1][1])+2*b[i];
else
dp[i][2]=min(dp[i-1][0],min(dp[i-1][1],dp[i-1][2]))+2*b[i];
}
}
inline void print()
{
printf("%lld\n",min(min(dp[n][0],dp[n][1]),dp[n][2]));
}
int main()
{
int t=1;
scanf("%d",&t);
for(int i=1;i<=t;i++)
{
prework();
mainwork();
print();
}
return 0;
}