CF1866E题解
Jordan_Pan · · 题解
Preface
大年初一又来水题解了~~~
题目传送门
题目大意:一栋大楼有
1.一个人从楼层
2.一座电梯改变运行状态,如果它之前可运行,那么从这一天开始变得不可运行,否则从这一天开始变得可运行。
你需要求出满足所有乘客要求情况下使用的最小花费。
数据范围:
Analysis
我们发现
考虑 dp。设
我们发现,考虑第
比如现在要算
接下来考虑如何转移。如果没有操作
时间复杂度
于是我们就做完了,只不过细节挺多的。
Code
#include<bits/stdc++.h>
#define inf (long long)1<<45
#define int long long
using namespace std;
const int _=305;
int n,q[_],d,a[4][25][_],lg[_];
void ST(int w){
for(int i=1;(1<<i)<=q[0];i++)
for(int j=0;j+(1<<i)-1<=q[0];j++)
a[w][i][j]=min(a[w][i-1][j],a[w][i-1][j+(1<<i-1)]);
}
int Min(int w,int l,int r){
int g=lg[r-l+1];
return min(a[w][g][l],a[w][g][r-(1<<g)+1]);
}
int x[_],y[_],mp[_];
int f[_][_][_],ans;
bool f1=0,f2=0,f3=0;
变量名清晰易懂
signed main(){
scanf("%lld%lld",&n,&q[0]);
for(int i=0;i<4;i++)
for(int j=0;j<25;j++)
for(int k=0;k<_;k++)
a[i][j][k]=inf;
for(int i=1;i<=q[0];i++)
scanf("%lld",&a[0][0][i]);
for(int i=1;i<=q[0];i++){
scanf("%lld",&q[i]);
if(q[i]==1){
d++;mp[d]=i;
scanf("%lld%lld",&x[d],&y[d]);
}
else{
int x;
scanf("%lld",&x);
if(x==1)f1^=1;
if(x==2)f2^=1;
if(x==3)f3^=1;
}
if(!f1)a[1][0][i]=a[0][0][i];
if(!f2)a[2][0][i]=a[0][0][i];
if(!f3)a[3][0][i]=a[0][0][i];
}
if(!d){
printf("0\n");
return 0;
}
lg[1]=0;
for(int i=2;i<=q[0];i++)
lg[i]=lg[i>>1]+1;
mp[0]=0;y[0]=1;
ST(1);ST(2);ST(3);
for(int i=0;i<=d;i++)
for(int j=0;j<=d;j++)
for(int k=0;k<=d;k++)
f[i][j][k]=inf;
f[0][0][0]=0;d=0;
for(int i=1;i<=q[0];i++){
if(q[i]==2)continue;
d++;
int Cost1,Cost2,Cost3,cost1,cost2,cost3,c1ost,c2ost,c3ost;
cost1=a[1][0][mp[d]]*abs(x[d]-y[d]);
c1ost=Min(1,mp[d-1],mp[d])*abs(x[d]-y[d-1]);
cost2=a[2][0][mp[d]]*abs(x[d]-y[d]);
c2ost=Min(2,mp[d-1],mp[d])*abs(x[d]-y[d-1]);
cost3=a[3][0][mp[d]]*abs(x[d]-y[d]);
c3ost=Min(3,mp[d-1],mp[d])*abs(x[d]-y[d-1]);
for(int j=0;j<d;j++)
for(int k=0;k<d;k++){
f[d][j][k]=min(f[d][j][k],f[d-1][j][k]+c1ost+cost1);
f[j][d][k]=min(f[j][d][k],f[j][d-1][k]+c2ost+cost2);
f[j][k][d]=min(f[j][k][d],f[j][k][d-1]+c3ost+cost3);
if(j==d-1)continue;
Cost1=Min(1,mp[k],mp[d])*abs(x[d]-y[k]);
Cost2=Min(2,mp[k],mp[d])*abs(x[d]-y[k]);
Cost3=Min(3,mp[k],mp[d])*abs(x[d]-y[k]);
f[d][d-1][j]=min(f[d][d-1][j],f[k][d-1][j]+Cost1+cost1);
f[d][j][d-1]=min(f[d][j][d-1],f[k][j][d-1]+Cost1+cost1);
f[d-1][d][j]=min(f[d-1][d][j],f[d-1][k][j]+Cost2+cost2);
f[j][d][d-1]=min(f[j][d][d-1],f[j][k][d-1]+Cost2+cost2);
f[d-1][j][d]=min(f[d-1][j][d],f[d-1][j][k]+Cost3+cost3);
f[j][d-1][d]=min(f[j][d-1][d],f[j][d-1][k]+Cost3+cost3);
}
}
ans=inf;
for(int j=0;j<d;j++)
for(int k=0;k<d;k++){
ans=min(ans,f[d][j][k]);
ans=min(ans,f[j][d][k]);
ans=min(ans,f[j][k][d]);
}
printf("%lld\n",ans);
return 0;
}码风严谨
Postscribe
调了两年,怒了,不写注释了,让代码自己猜。
在新的一年里,祝大家心想事成,万事如意~~~