2017, X Samara Regional Intercollegiate Programming Contest E. Bonuses and Teleports (思维,模拟)

-
题意:在\(x\)轴上有很多传送点和钻石,当位于传送点上时,可以传送到其他任意传送点(不记操作数),位于钻石上时可以吃掉它,每次可以移动一个单位,问最少多少次可以吃掉所有的钻石.
-
题解:对于某个位置上的钻石,我们可以从它左边的传送点走过来,或者从它右边的传送点走过来,又或者从上一个钻石的位置直接走过来,我们每次在这三个距离中取最小即可.具体怎么实现呢?我们首先考虑左右传送点的情况,遍历每个钻石的位置,然后记录当前这个钻石到左传送点或右传送点的最小距离,之后再次遍历钻石位置,比较\(上个钻石走回传送门的距离加上从传送门走到当前钻石的最小距离\)和\(上个钻石的位置直接走到当前位置的距离\),取\(min\)贡献给答案即可.
-
代码:
int n,m; ll t[N],b[N]; ll c[N]; ll res; int main() { //ios::sync_with_stdio(false);cin.tie(0); scanf("%d %d",&n,&m); for(int i=1;i<=n;++i){ scanf("%lld",&t[i]); } for(int i=1;i<=m;++i){ scanf("%lld",&b[i]); } b[0]=b[m+1]=t[1]; t[n+1]=INF; int j=0; ll tmp; for(int i=1;i<=m;++i){ //求两个tele之间到钻石的min while(t[j+1]<=b[i]) j++; if(j==0) c[i]=INF; else c[i]=b[i]-t[j]; if(j<n) tmp=t[j+1]-b[i]; else tmp=INF; c[i]=min(c[i],tmp); } c[0]=c[m+1]=0; for(int i=1;i<=m+1;++i){ ll dis=abs(b[i]-b[i-1]); dis=min(dis,c[i-1]+c[i]); res+=dis; } printf("%lld\n",res); return 0; }
𝓐𝓬𝓱𝓲𝓮𝓿𝓮𝓶𝓮𝓷𝓽 𝓹𝓻𝓸𝓿𝓲𝓭𝓮𝓼 𝓽𝓱𝓮 𝓸𝓷𝓵𝔂 𝓻𝓮𝓪𝓵
𝓹𝓵𝓮𝓪𝓼𝓾𝓻𝓮 𝓲𝓷 𝓵𝓲𝓯𝓮

浙公网安备 33010602011771号