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;
}

posted @ 2011-07-01 20:04  zqynux  阅读(281)  评论(0编辑  收藏  举报