看到了觉得无法下手啊!但是看了题解就知道了(是废话不~濮~)。
设p[i]是第i个请求的地方,那么根据题意能够知道在完成第i个请求之前,三个人有一个是在p[i - 1],而且也可以知道完成第i个请求后,有一个人在p[i]上。设完成第i请求之前(未完成)三个人的位置分别是x,y,p[i-1],那么完成请求后就会有三种情况,x前往p[i],三个人的坐标变成y,p[i-1],p[i];或者y前往p[i],三个人的坐标变成x,p[i - 1], p[i];或者p[i - 1]前往p[i],变成:x,y,p[i]。
自然有下面的方程:
- f[i][x][y] = f[i - 1][x][y] + map[p[i - 1]][p[i]]
- f[i][x][p[i - 1]] = f[i - 1][x][y] + map[y][p[i]]
- f[i][y][p[i - 1]] = f[i - 1][x][y] + map[x][p[i]]
代码:
#include <stdio.h>
#include <stdlib.h>
int f[2][201][201];
int map[201][201];
#define min(a, b) ((a)<(b)?(a):(b))
void clean(int n, int k)
{
int i, j;
for(i = 1; i <= n; i++){
for(j = 1; j <= n; j++){
f[k][i][j] = 0xFFFFFFF;
}
}
}
int main(int argc, char **argv)
{
int i, j, k;
int n, m;
int a, b;
int ans;
scanf("%d%d", &n, &m);
for(i = 1; i <= n; i++){
for(j = 1; j <= n; j++){
scanf("%d", &map[i][j]);
if(i == j){
map[i][j] = 0;
}
}
}
clean(n, 1);
scanf("%d", &a);
f[1][1][2] = f[1][2][1] = map[3][a];
f[1][2][3] = f[1][3][2] = map[1][a];
f[1][1][3] = f[1][3][1] = map[2][a];
for(i = 2; i <= m; i++){
scanf("%d", &b);
clean(n, i % 2);
for(j = 1; j <= n; j++){
for(k = 1; k <= n; k++){
if(k == j){
continue;
}
f[i % 2][j][k] = min(f[i % 2][j][k], f[(i - 1) % 2][j][k] + map[a][b]);
f[i % 2][j][a] = min(f[i % 2][j][a], f[(i - 1) % 2][j][k] + map[k][b]);
f[i % 2][a][k] = min(f[i % 2][a][k], f[(i - 1) % 2][j][k] + map[j][b]);
}
}
a = b;
}
ans = 0xFFFFFFF;
for(i = 1; i <= n; i++){
for(j = 1; j <= n; j++){
if(ans > f[m % 2][i][j]){
ans = f[m % 2][i][j];
}
}
}
printf("%d\n", ans);
return 0;
}