動態規劃-----線性

星竹z發表於2024-04-02

[TJOI2007] 線段(洛谷P3842)

題目描述

在一個 \(n \times n\) 的平面上,在每一行中有一條線段,第 \(i\) 行的線段的左端點是\((i, L_{i})\),右端點是\((i, R_{i})\)

你從 \((1,1)\) 點出發,要求沿途走過所有的線段,最終到達 \((n,n)\) 點,且所走的路程長度要儘量短。

更具體一些說,你在任何時候只能選擇向下走一步(行數增加 \(1\))、向左走一步(列數減少 \(1\))或是向右走一步(列數增加 \(1\))。當然,由於你不能向上行走,因此在從任何一行向下走到另一行的時候,你必須保證已經走完本行的那條線段。

輸入格式

第一行有一個整數 \(n\)

以下 \(n\) 行,在第 \(i\) 行(總第 \((i+1)\) 行)的兩個整數表示 \(L_i\)\(R_i\)

輸出格式

僅包含一個整數,你選擇的最短路程的長度。

樣例 #1

樣例輸入 #1

6
2 6
3 4
1 3
1 2
3 6
4 5

樣例輸出 #1

24

樣例解釋

我們選擇的路線是

 (1, 1) (1, 6)
 (2, 6) (2, 3)
 (3, 3) (3, 1)
 (4, 1) (4, 2)
 (5, 2) (5, 6)
 (6, 6) (6, 4) (6, 6)

不難計算得到,路程的總長度是 \(24\)

對於 \(100\%\) 的資料中,\(n \le 2 \times 10^4\)\(1 \le L_i \le R_i \le n\)








解答

動態規劃-----線性

#include <iostream>
using namespace std;
const int N = 2e4 + 10;
typedef pair<int, int> PII;
#define L first
#define R second

PII a[N];
int n;
int f[N][2];

int main()
{
	scanf("%d", &n);
	for (int i = 1; i <= n; i++) 
		scanf("%d%d", &a[i].L, &a[i].R);
	
	
	f[1][0] = abs(a[1].R - 1) + abs(a[1].L - a[1].R);
	f[1][1] = abs(a[1].R - 1);

	for (int i = 2; i <= n; i++)//狀態轉移
	{
		int x1 = f[i - 1][0] + abs(a[i - 1].L - a[i].R) + abs(a[i].R- a[i].L);
		int y1 = f[i - 1][1] + abs(a[i - 1].R - a[i].R) + abs(a[i].R - a[i].L);
		f[i][0] = min(x1, y1) + 1;
		
		int x2 = f[i - 1][0] + abs(a[i - 1].L - a[i].L) + abs(a[i].L -  a[i].R);
		int y2 = f[i - 1][1] + abs(a[i - 1].R- a[i].L) + abs(a[i].L - a[i].R);
		f[i][1] = min(x2, y2) + 1;
	}

	printf("%d", min(f[n][0] + abs(a[n].L - n), f[n][1] + abs(a[n].R - n)));//最後的答案還要加上到(n,n)的距離
	return 0;
}

相關文章