线性dp,274. 移动服务,《算法竞赛进阶指南》

274. 移动服务 - AcWing题库

一个公司有三个移动服务员,最初分别在位置 1,2,3 处。

如果某个位置(用一个整数表示)有一个请求,那么公司必须指派某名员工赶到那个地方去。

某一时刻只有一个员工能移动,且不允许在同样的位置出现两个员工。

从 p 到 q 移动一个员工,需要花费 c(p,q)。

这个函数不一定对称,但保证 c(p,p)=0。

给出 N 个请求,请求发生的位置分别为 p1∼pN。

公司必须按顺序依次满足所有请求,且过程中不能去其他额外的位置,目标是最小化公司花费,请你帮忙计算这个最小花费。

输入格式

第 1 行有两个整数 L,N,其中 L 是位置数量,N 是请求数量,每个位置从 1 到 L 编号。

第 2 至 L+1 行每行包含 L 个非负整数,第 i+1 行的第 j 个数表示 c(i,j),并且它小于 20002000。

最后一行包含 N 个整数,是请求列表。

一开始三个服务员分别在位置 1,2,31,2,3。

输出格式

输出一个整数 M,表示最小花费。

数据范围

3≤L≤200
1≤N≤1000

输入样例:

5 9
0 1 1 1 1
1 0 2 3 2
1 1 0 4 1
2 1 5 0 1
4 2 3 4 0
4 2 4 1 5 4 3 2 1

输出样例:

5

 解析

 题目非常好,但我还没吃透,理解的不够深,解析先不写,现附上acwing的题解,等完全掌握后再写解析

AcWing 274. 移动服务 - AcWing 

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

using namespace std;
typedef long long LL;
const int N = 205, M = 1e3 + 5;
int l, n;
int c[N][N];
int p[M];
int f[M][N][N];

int main() {
	cin >> l >> n;
	for (int i = 1; i <= l; i++) {
		for (int j = 1; j <= l; j++) {
			scanf("%d", &c[i][j]);
		}
	}
	for (int i = 1; i <= n; i++)
		scanf("%d", &p[i]);
	memset(f, 0x3f, sizeof(f));
	f[0][1][2] = 0;
	p[0] = 3;
	for (int i = 0; i < n; i++) {
		for (int x = 1; x <= l; x++) {
			for (int y = 1; y <= l; y++) {
				int z = p[i], u = p[i + 1], v = f[i][x][y];
				if (y == x || z == y || z == x)continue;
				f[i + 1][x][y] = min(f[i + 1][x][y], v + c[z][u]);
				f[i + 1][z][y] = min(f[i + 1][z][y], v + c[x][u]);
				f[i + 1][x][z] = min(f[i + 1][x][z], v + c[y][u]);
			}
		}
	}
	int ans = 0x3f3f3f3f;
	for (int i = 1; i <= l; i++) {
		for (int j = 1; j <= l; j++) {
			int z = p[n];
			if (i== j || z == j || z == i)continue;
			ans = min(ans, f[n][i][j]);
		}
	}
	cout << ans << endl;
	return 0;
}

你可能感兴趣的:(#,线性dp,算法,数据结构,线性dp)