(\)
(Description)
一个(N imes N) 的网格,每行有一段要必走,求从((1,1))到((N,N))的最短路长度。
- (Nle 2 imes10^4)
(\)
(Solution)
论读题的重要性......
注意到除了最后一行,每一行结束处一定在是线段的某一侧,否则其他位置一定会多走一段从端点到这里的距离。
然后就是(f[i][0/1])表示到第(i)行线段左端点(/)右端点最小步数,转移就是四个了。
转移不用想太多,如果你要到左端点结束,那就得先到右端点,所以答案就是线段长度(+)上一状态到右端点距离。
右端点同理。注意答案和转移增量的处理。
(\)
(Code)
#include<cmath>
#include<cctype>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define R register
#define gc getchar
#define N 20010
using namespace std;
inline int rd(){
int x=0; bool f=0; char c=gc();
while(!isdigit(c)){if(c=='-')f=1;c=gc();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=gc();}
return f?-x:x;
}
int n,ans=0,l[N],r[N],f[N][2];
int main(){
n=rd();
memset(f,0x3f,sizeof(f));
l[1]=rd(); r[1]=rd();
f[1][0]=r[1]-1+r[1]-l[1];
f[1][1]=r[1]-1;
for(R int i=2;i<=n;++i){
l[i]=rd(); r[i]=rd();
f[i][0]=min(f[i][0],f[i-1][0]+abs(l[i-1]-r[i])+r[i]-l[i]+1);
f[i][0]=min(f[i][0],f[i-1][1]+abs(r[i-1]-r[i])+r[i]-l[i]+1);
f[i][1]=min(f[i][1],f[i-1][0]+abs(l[i-1]-l[i])+r[i]-l[i]+1);
f[i][1]=min(f[i][1],f[i-1][1]+abs(r[i-1]-l[i])+r[i]-l[i]+1);
}
ans=min(f[n][0]+n-l[n],f[n][1]+n-r[n]);
printf("%d
",ans);
return 0;
}