0
点赞
收藏
分享

微信扫一扫

CF 253C(找中转行)


C. 光标移动



time limit per test



memory limit per test



input



output



文本编辑器有n行,每行k个字符(显然光标有k+1个位置,标记为1..k+1.

有4个操作:


  • 光标将向下移1行,列不变。如果上一行字符太少,则光标跑到行末。

  • 光标向左移1格,操作不能在行首进行。
    (r1, c1) 移向(r2, c2)最小步数.



Input



n (1 ≤ n ≤ 100) . 第二行 n个整数a1, a2, ..., an (0 ≤ ai ≤ 105), 表示每行字符数. 第三行4个整数 r1, c1, r2, c2 (1 ≤ r1, r2 ≤ n, 1 ≤ c1 ≤ ar1 + 1, 1 ≤ c2 ≤ ar2 + 1).



Output



输出最小步数



Sample test(s)



input



4 2 1 6 4 3 4 4 2



output



3



input



4 10 5 6 4 1 11 4 2



output



6



input



3 10 1 10 1 10 1 1



output



3



Note



第一组数据若为

123

12

123s567

1t345

则最小操作为 "Left", "Down", "Left".



显然除了直接移(先行后列)外,

唯一减少操作数的方法便是向中间以外的行数移,以求降低列的移动数。

一定要注意不是挪到每行直接取abs(行尾-c2)的,因为可能会有往返行尾的路上有更小的,直接取行尾可能拉近它和c2的距离,但是这种操作是不可行的。


#include<cstdio>
#include<functional>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<iostream>
using namespace std;
#define MAXN (10000+100)
int a[MAXN],n;
int abs2(int a,int b)
{
if (a<b) return b-a;
else return a-b;
}
int main()
{
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
scanf("%d",&n);
for (int i=1;i<=n;i++) scanf("%d",&a[i]);
int r1,c1,r2,c2;
scanf("%d%d%d%d",&r1,&c1,&r2,&c2);
int mi=c1,ans=0,tans=1000000000;
if (r1<r2)
{
ans=r2-r1;
for (int i=r1+1;i<=r2;i++) mi=min(mi,a[i]+1);
tans=min(tans,ans+abs(mi-c2));
for (int i=r1-1,cost=2,mii=mi;i>=1;i--,cost+=2)
{
mii=min(mii,a[i]+1);
tans=min(tans,ans+cost+abs(mii-c2));
}
for (int i=r2+1,cost=2,mii=mi;i<=n;i++,cost+=2)
{
mii=min(mii,a[i]+1);
tans=min(tans,ans+cost+abs(mii-c2));
}
}
else
{
ans=r1-r2;
for (int i=r1-1;i>=r2;i--) mi=min(mi,a[i]+1);
tans=min(tans,ans+abs(mi-c2));
for (int i=r2-1,cost=2,mii=mi;i>=1;i--,cost+=2)
{
mii=min(mii,a[i]+1);
tans=min(tans,ans+cost+abs(mii-c2));
}
for (int i=r1+1,cost=2,mii=mi;i<=n;i++,cost+=2)
{
mii=min(mii,a[i]+1);
tans=min(tans,ans+cost+abs(mii-c2));
}
}
cout<<tans<<endl;
return 0;
}



举报

相关推荐

0 条评论