[Codeforces 1201D]Treasure Hunting(DP)

[Codeforces 1201D]Treasure Hunting(DP)

Face questions

There is a n * m grid, with k on the treasure box, a person from (1,1) starting can be left or right away, but can not go down. Given q columns, can go up on these columns, other columns can not go up. It can be repeated through the same point. Request from the (1,1), goes through the shortest path length of all the treasures

\(n,m,k,q \leq 2 \times 10^5\)

analysis

Greedy reasons, we should go layer by layer in rows. Each line should come from the leftmost rightmost treasures treasures, or come to the treasures left from the rightmost treasures, and then find the nearest one can go up the column, go to another line.

Set \ (dp [i] [0/1 ] \) represents the current in the leftmost row i treasure or treasures rightmost has been completed for all the shortest distance from the row treasures

So long as there is a treasure of the rows pre, classification talk about four kinds of transfer

\ (dp [i] [0 ] \) you need to go to the far right of the i-th row, and then went to the extreme left from the far right of the i-th row

\ (dp [i] [1 ] \) you need to go to the far right of the i-th row, and then went to the extreme left from the far right of the i-th row

Another issue is how the distance (x2, y2) is calculated (x1, y1). We pretreatment column i can go up recently left column lb [i], and more recently in the rightmost column rb [i], then we take the column must lb [y1], lb [y2], rb [ y1], rb [a Y2] of four.

As shown below, assuming that y1 <y2, go lb [y1] a left side is clearly not lb [y1] preferably, take rb [y2] a right side is clearly not rb [y2] excellent, while walking rb [y1], lb [Y2] and directly down the middle of the column rb [y1], lb [y2] as

After this four from the upward out the statistics on it

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define maxn 200000 
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
int n,m,k,q;
vector<int>a[maxn+5];
int lb[maxn+5],rb[maxn+5];
int col[maxn+5]; 
ll dp[maxn+5][2];//走到最左侧/最右侧结束 
ll calc(int y1,int y2,int line){//从y1到第line列,走上去,再到y2
    return (ll)abs(y1-line)+abs(y2-line);
}
ll dist(int x1,int y1,int x2,int y2){
    ll distx=abs(x1-x2);
    ll disty=min(min(calc(y1,y2,lb[y1]),calc(y1,y2,lb[y2])),min(calc(y1,y2,rb[y1]),calc(y1,y2,rb[y2])));
    return distx+disty;
}
int main(){
    int x,y;
    scanf("%d %d %d %d",&n,&m,&k,&q);
    for(int i=1;i<=k;i++){
        scanf("%d %d",&x,&y);
        a[x].push_back(y); 
    }
    for(int i=1;i<=q;i++){
        scanf("%d",&col[i]);
    }
    sort(col+1,col+1+q);
    col[0]=-INF;
    col[q+1]=INF;
    for(int i=1;i<=m;i++){
        lb[i]=col[lower_bound(col+1,col+1+q,i)-col-1];
        rb[i]=col[lower_bound(col+1,col+1+q,i)-col];
    } 
    
    sort(a[1].begin(),a[1].end());
    if(!a[1].empty()){
        dp[1][0]=dp[1][1]=a[1].back()-1;
        a[1][0]=a[1].back();
        //第一行必须从最后一个关键点往上走,否则就走不完所有关键点 
    }else{
        a[1].push_back(1);
        dp[1][0]=dp[1][1]=0;
    }
    int last=1;
    for(int i=2;i<=n;i++){
        if(!a[i].empty()){
            sort(a[i].begin(),a[i].end());
            ll l_to_l=dp[last][0]+dist(last,a[last].front(),i,a[i].front());//从pre行最左侧走到i行最左侧
            ll r_to_l=dp[last][1]+dist(last,a[last].back(),i,a[i].front()); //从pre行最右侧走到i行最左侧
            ll l_to_r=dp[last][0]+dist(last,a[last].front(),i,a[i].back());//从pre行最左侧走到i行最右侧
            ll r_to_r=dp[last][1]+dist(last,a[last].back(),i,a[i].back());//从pre行最右侧走到i行最右侧
            ll now=a[i].back()-a[i].front();//走完当前行的代价 
            dp[i][0]=min(l_to_r,r_to_r)+now;//先走到最右侧,最后到最左侧 
            dp[i][1]=min(l_to_l,r_to_l)+now;//先走到最左侧,最后到最右侧 
            last=i;
        }
    } 
    printf("%I64d\n",min(dp[last][0],dp[last][1]));
    
}

Guess you like

Origin www.cnblogs.com/birchtree/p/11301444.html