TYVJ 1061 Mobile Service 解题报告
看到了觉得无法下手啊!但是看了题解就知道了(是废话不~濮~)。
设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; }