码迷,mamicode.com
首页 > 其他好文 > 详细

[CF1201D] Treasure Hunting - dp

时间:2020-04-03 22:17:49      阅读:66      评论:0      收藏:0      [点我收藏+]

标签:for   its   math   cin   int   sig   fine   一个人   std   

有一个 \(n\times m\) 的网格,方格上有 \(k\) 个宝藏,一个人从 \((1,1)\) 出发,可以向左或者向右走,但不能向下走。给出 \(q\) 个列,在这些列上可以向上走,其他列不能向上走。可以重复经过同一个点。求从 \((1,1)\) 出发,经过所有宝藏的最短路径长度。\(n,m,k,q\leq 2\times 10^5\)

Solution

\(f[i][0/1]\) 表示从 \((0,0)\) 走到 \(i\) 行的左侧/右侧,并遍历了 \(1 \to i-1\) 行的所有宝物的最短路径长度

(挺怕这种题的)

#include <bits/stdc++.h>
using namespace std;

#define int long long
const int N = 500005;

int n,m,k,q,l[N],r[N],f[N][2],b[N],pl[N],pr[N];

int dist(int p,int q) {
    if(p>q) swap(p,q);
    if(pr[p]<=q || pl[q]>=p) return 0;
    return min(pr[q]-q,p-pl[p]);
}

signed main() {
    ios::sync_with_stdio(false);
    cin>>n>>m>>k>>q;
    for(int i=1;i<=n;i++) l[i]=1e9, r[i]=0;
    for(int i=1;i<=k;i++) {
        int t1,t2;
        cin>>t1>>t2;
        l[t1]=min(l[t1],t2);
        r[t1]=max(r[t1],t2);
    }
    for(int i=1;i<=q;i++) {
        int t1;
        cin>>t1;
        b[t1]=1;
    }
    pl[0]=-1e9;
    for(int i=1;i<=m;i++) {
        if(b[i]==1) pl[i]=i;
        else pl[i]=pl[i-1];
    }
    pr[m+1]=1e9;
    for(int i=m;i>=1;--i) {
        if(b[i]==1) pr[i]=i;
        else pr[i]=pr[i+1];
    }
    if(r[1]) f[1][0]=l[1]-1, f[1][1]=r[1]-1;
    else l[1]=1,r[1]=1,f[1][0]=f[1][1]=0;
    int ans=f[1][1];
    for(int i=2;i<=n;i++) {
        if(r[i]==0) {
            f[i][0]=f[i-1][0];
            f[i][1]=f[i-1][1];
            l[i]=l[i-1];
            r[i]=r[i-1];
            ++f[i][0]; ++f[i][1];
            continue;
        }
        f[i][0]=min(f[i-1][0]+2*dist(r[i-1],l[i])+abs(l[i]-r[i-1])+r[i-1]-l[i-1],
                    f[i-1][1]+2*dist(l[i-1],l[i])+abs(l[i]-l[i-1])+r[i-1]-l[i-1]);
        f[i][1]=min(f[i-1][0]+2*dist(r[i-1],r[i])+abs(r[i]-r[i-1])+r[i-1]-l[i-1],
                    f[i-1][1]+2*dist(l[i-1],r[i])+abs(r[i]-l[i-1])+r[i-1]-l[i-1]);
        ++f[i][0]; ++f[i][1];
        //cout<<"i="<<i<<" "<<f[i][0]+r[i-1]-l[i-1]<<" "<<f[i][1]+r[i]-l[i]<<endl;
        ans=min(f[i][0],f[i][1])+r[i]-l[i];
    }
    cout<<ans;
}

[CF1201D] Treasure Hunting - dp

标签:for   its   math   cin   int   sig   fine   一个人   std   

原文地址:https://www.cnblogs.com/mollnn/p/12629011.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!