题意
给定两串项链 , 找出使得两串项链相等的最小代价 , 可以自己选择起点。
思路
将问题抽象成图论问题,使用Floyd算法求出任意两点之间的最短路。再使用贪心做法,枚举每个起点即可。
其中,存在一步优化。即,在枚举起点时,只需要枚举B串项链的每个点,A串固定1号位置即可。
举例:
A : 1 2 3
B : a b c 这里给出a b c 只是为了好区分
起点 : 1 a
1 2 3
a b c
起点 : 1 b
1 2 3
b c a
起点 : 1 c
1 2 3
c a b
就随便拿一个来说: 起点为 1 c
其实它已经枚举完 起点 1 c 、 2 a 、 3 b
那么 枚举3种起点 其实已经枚举完 9 种起点了
本题难度一般,主要是想到如何在正确时间复杂度贪心存在难度
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#define LL long long
const int N = 400 , INF = INT_MAX;
int n , m;
LL g[N + 1][N + 1];
int main() {
std::ios::sync_with_stdio(0);
std::cin.tie(0);
std::cout.tie(0);
std::cin >> n >> m;
std::vector<int> t1(2 * n + 1) , t2(2 * n + 1);
for (int i = 1; i <= n; i ++ ){
std::cin >> t1[i];
t1[i + n] = t1[i];
}
for (int i = 1; i <= n; i ++ ) {
std::cin >> t2[i];
t2[i + n] = t2[i];
}
for (int i = 1; i <= N; i ++ )
for (int j = 1; j <= N; j ++ )
if (i != j) g[i][j] = INF;
while (m -- ){
LL a , b , c;
std::cin >> a >> b >> c;
g[a][b] = std::min(g[a][b] , c);
}
for (int k = 1; k <= N; k ++ )
for (int i = 1; i <= N; i ++ )
for (int j = 1; j <= N; j ++ )
g[i][j] = std::min(g[i][j] , g[i][k] + g[k][j]);
LL ans = INF;
for (int i = 1; i <= n; i ++ ) {
LL sum = 0;
bool ok = 1;
int l = i , r = i + n - 1; // 选择 l 作为起点 , r 作为终点
for (int j = l , k = 1; j <= r; j ++ , k ++ )
if (t1[k] != t2[j]){
int u = t1[k] , v = t2[j];
sum += std::min(g[u][v] , g[v][u]);
if (sum >= INF) {
ok = 0;
break;
}
}
if (ok) ans = std::min(ans , sum);
}
std::cout << (ans == INF ? -1 : ans) << '\n';
return 0;
}