链接: https://codeforces.com/contest/1201/problem/D
题面:
You are on the island which can be represented as a n×m table. The rows are numbered from 1 to n and the columns are numbered from 1 to m. There are k treasures on the island, the i-th of them is located at the position (ri,ci).
Initially you stand at the lower left corner of the island, at the position (1,1). If at any moment you are at the cell with a treasure, you can pick it up without any extra time. In one move you can move up (from (r,c) to (r+1,c)), left (from (r,c) to (r,c−1)), or right (from position (r,c) to (r,c+1)). Because of the traps, you can’t move down.
However, moving up is also risky. You can move up only if you are in a safe column. There are q safe columns: b1,b2,…,bq. You want to collect all the treasures as fast as possible. Count the minimum number of moves required to collect all the treasures.
Input
The first line contains integers n, m, k and q (2≤n,m,k,q≤2e5, q≤m) — the number of rows, the number of columns, the number of treasures in the island and the number of safe columns.
Each of the next k lines contains two integers ri,ci, (1≤ri≤n, 1≤ci≤m) — the coordinates of the cell with a treasure. All treasures are located in distinct cells.
The last line contains q distinct integers b1,b2,…,bq (1≤bi≤m) — the indices of safe columns.
Output
Print the minimum number of moves required to collect all the treasures.
题意: 给你一个矩形,起始点在(1,1),在一些格子里有宝物,你需要将整个图中的宝物全部收集起来,而且你不能向下走,而且只有在所给出的列上你才能向上走,问最少要走多少格
思路: 由于数据过大,不可能将整个图开出来
所以我们可以预处理每一行的所在宝物的最左边与最右边,然后进行由下往上dp,上行的点由下行的所在宝物的最左边与最右边出发得到
#include
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int N=2e5+5;
ll n,m,k,q,x,y,a[N][2],dp[N][2],b[N];
ll sl(int j,int u,int i,int v)
{
ll sum=INF,sum1=INF;
ll p=lower_bound(b+1,b+1+q,a[j][u])-b;
if(p<=q)
sum=abs(a[j][u]-b[p])+abs(a[i][v]-a[i][v^1])+abs(b[p]-a[i][v^1]);
p=upper_bound(b+1,b+1+q,a[j][u])-b-1;
if(p)
sum1=abs(a[j][u]-b[p])+abs(a[i][v]-a[i][v^1])+abs(b[p]-a[i][v^1]);
return min(sum1,sum);
}
int main()
{
scanf("%lld%lld%lld%lld",&n,&m,&k,&q);
for(int i=1;i<=n;i++)
{
a[i][0]=INF;
a[i][1]=-INF;
dp[i][0]=dp[i][1]=(1ll<<60);
}
for(int i=1;i<=k;i++)
{
scanf("%d%d",&x,&y);
a[x][0]=min(y,a[x][0]);
a[x][1]=max(y,a[x][1]);
}
a[1][0]=1,a[1][1]=max(a[1][1],1ll);
for(int i=1;i<=q;i++)
scanf("%lld",&b[i]);
sort(b+1,b+1+q);
int j=1;
dp[1][0]=abs(a[1][1]-1)+abs(a[1][1]-a[1][0]),dp[1][1]=abs(a[1][1]-1);
for(int i=2;i<=n;i++)
{
if(a[i][0]==INF)
continue;
for(int v=0;v<2;v++)
{
for(int u=0;u<2;u++)
{
dp[i][v]=min(dp[i][v],dp[j][u]+sl(j,u,i,v)+i-j);
}
}
j=i;
}
printf("%lld\n",min(dp[j][0],dp[j][1]));
return 0;
}