P3842 [TJOI2007]线段

原题链接

考察:线性dp

思路:

        这道题就和POJ 1661差不多.f[i][0/1]表示到达第i条线段的0(左),1(右)的最小距离.

        f[i][0] = min(f[i-1][0]+i-1条线左端点到i条线左端点的最短距离,f[i-1][1]+i-1条线右端点到第i条线左端点的最小值)

        同理右端点.

 1 #include <iostream>
 2 #include <cstring>
 3 using namespace std;
 4 typedef pair<int,int> PII;
 5 const int N = 20010;
 6 int n,f[N][2];
 7 PII p[N];
 8 int getl(int x,int idx)//x到左点的最小值 
 9 {
10     int l = p[idx].first,r = p[idx].second,res = 0;
11     if(x<=l) res = 2*r-l-x;
12     else if(x>l&&x<r) res = min(x-l+(r-l)*2,r-x+r-l);
13     else res = x-l;
14     return res; 
15 }
16 int getr(int x,int idx)//x到右端点的最小值. 
17 {
18     int l = p[idx].first,r = p[idx].second,res = 0;
19     if(x<=l) res = r-x;
20     else if(x>l&&x<r) res = min(x-l+r-l,r-x+(r-l)*2);
21     else res = x+r-2*l;
22 }
23 int solve()
24 {
25     p[0].first = 1,p[0].second = 1;
26     for(int i=1;i<=n;i++)
27     {
28         int l = p[i-1].first,r = p[i-1].second;
29         f[i][0] = min(f[i-1][0]+getl(l,i),f[i-1][1]+getl(r,i));
30         f[i][1] = min(f[i-1][0]+getr(l,i),f[i-1][1]+getr(r,i));
31         if(i!=1) f[i][0]++,f[i][1]++;
32     }
33     int l = p[n].first,r = p[n].second;
34     int ans = min(f[n][0]+abs(n-l),f[n][1]+abs(n-r));
35     return ans;
36 }
37 int main() 
38 {
39     scanf("%d",&n);
40     for(int i=1;i<=n;i++) scanf("%d%d",&p[i].first,&p[i].second);
41     int res = solve();
42     printf("%d\n",res);
43     return 0;
44 }

 

posted @ 2021-04-09 21:36  acmloser  阅读(74)  评论(0编辑  收藏  举报