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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章