CH 5102 Mobile Service

题目传送门

\(f_{i,j,k}\)表示到第i次,一个人在j,一个人在k的最小花费.
因为其中一个人一定在\(p_i\)上.
\(f_{i+1,j,k} = min\) { \(f_{i+1,j,k},f_{i,j,k}\) } \(+c_{p_i,p_{i+1}}\) 第三人跳到本次指定的位置.
\(f_{i+1,p_i,k} = min\) { \(f_{i+1,p_i,k},f_{i,j,k}\) } \(+c_{j,p_{i+1}}\) 第一个人跳到本次指定的位置.
\(f_{i+1,j,p_i} = min\) { \(f_{i+1,j,p_i},f_{i,j,k}\) } \(+c_{k,p_{i+1}}\) 第二个人跳到本次指定的位置.

#include<iostream>
#include<cstdio>
#include<cstring>

using namespace std;

long long n,l,a[201][201],f[2][201][201],p[1001],q,ans = 2100000000;

inline long long mx() {
	long long s = 0,w = 1;
	char ch = getchar();
	while(ch < '0' || ch > '9') {
		if(ch == '-') w = -1;
		ch = getchar();
	}
	while(ch >= '0' && ch <= '9') {
		s = s * 10 + (ch - '0');
		ch = getchar();
	}
	return s * w;
}

int main() {
	l = mx();
	n = mx();
	memset(f,0x3f,sizeof(f));
	for(int i = 1;i <= l; i++)
		for(int j = 1;j <= l; j++)
			a[i][j] = mx();
	for(int i = 1;i <= n; i++)
		p[i] = mx();
	p[0] = 3;
	f[0][1][2] = 0;
	for(int i = 0;i < n; i++) {
		q ^= 1;
		for(int j = 1;j <= l; j++)
			for(int k = 1;k <= l; k++) {
				if(i == 0 && (j != 1 || k != 2)) continue;//初始位置时特殊处理 
				if(j != p[i+1] && k != p[i+1]) f[q][j][k] = min(f[q][j][k],f[q^1][j][k] + a[p[i]][p[i+1]]);
				if(p[i] != k && p[i] != p[i+1]) f[q][p[i]][k] = min(f[q][p[i]][k],f[q^1][j][k] + a[j][p[i+1]]);
				if(j != p[i] && p[i] != p[i+1]) f[q][j][p[i]] = min(f[q][j][p[i]],f[q^1][j][k] + a[k][p[i+1]]);
				f[q^1][j][k] = 0x3f3f3f3f;//将初始位置初始化,便于更新答案 
			}
	}
	for(int i = 1;i <= l; i++)
		for(int j = 1;j <= l; j++)
			if(i != j) ans = min(ans,f[q][i][j]);
	printf("%lld",ans);
	return 0;
} 
posted @ 2020-11-22 21:12  Mr^Simon  阅读(71)  评论(0编辑  收藏  举报