题目:http://codevs.cn/problem/1024/
思路:根据数据建立燕园路口连接矩阵,然后用floyd算法求解最有路径。题目,数据5有误,t与k数据颠倒即可得到答案92。
题解:
/* 1024 一塔湖图 */
#include <stdio.h>
#define DEBUG
#define MAXN 11 /* 最大面积 */
#define MAXT 101 /* 最多道路 */
#define MAXTIME 1000000 /* 最长时间 */
#define IMPOS -1 /* 无法通行标志 */
/* 方向定义 */
#define NORTH 0
#define SOUTH 1
#define WEST 2
#define EAST 3
/* 方向相对坐标 */
int posx[4]={0,0,-1,1};
int posy[4]={-1,1,0,0};
/* 湖泊结构体,边界(x1,y1), (x2,y2) */
struct _lake{
int x1, y1, x2, y2;
}lake[MAXN];
/* 无法通行道路结构体 */
struct _traffic{
int x1, y1;
int x2, y2;
}traffic[MAXT];
/* 十字路口结构体 */
typedef struct _crossing{
int x;
int y;
}crossing;
int n, m, t, k; /* 燕园尺寸n*m,无法通行道路数t,湖数k */
int an[MAXN], bm[MAXN]; /* 纵,横通行时间 */
crossing a, b; /* 起点位置,图书馆位置 */
int roads[MAXN][MAXN][MAXN][MAXN]; /* 燕园道路图 */
crossing queue[MAXT]; /* floyd操作队列 */
int inq[MAXN][MAXN]; /* 是否已存在于待操作队列标记 */
int dis[MAXN][MAXN]; /* 最优距离表 */
/* 绘制道路 */
void draw_roads(){
int x1, y1, x2, y2;
int i;
/* 南北道路通过时间 */
for(x1 = 1; x1 <= n; x1++){
x2 = x1;
for(y1 = 1; y1 < m ; y1++){
y2 = y1 + 1;
roads[x1][y1][x2][y2] = bm[y2] - bm[y1];
roads[x2][y2][x1][y1] = bm[y2] - bm[y1];
}
}
/* 东西道路通过时间 */
for(y1 = 1; y1 <= m; y1++){
y2 = y1;
for(x1 = 1; x1 <= n; x1++){
x2 = x1 + 1;
roads[x1][y1][x2][y2] = an[x2] - an[x1];
roads[x2][y2][x1][y1] = an[x2] - an[x1];
}
}
/* 导入无法通行道路 */
for(i = 1; i <= t; i++){
x1 = traffic[i].x1;
x2 = traffic[i].x2;
y1 = traffic[i].y1;
y2 = traffic[i].y2;
roads[x1][y1][x2][y2] = IMPOS;
roads[x2][y2][x1][y1] = IMPOS;
}
/* 导入湖泊数据 */
for(i = 1; i <= k; i++){
/* 从北到南,修改无法通行道路 */
for(y1 = lake[i].y1 + 1; y1 < lake[i].y2; y1++){
for(x1 = lake[i].x1; x1 < lake[i].x2; x1++){
x2 = x1 + 1;
roads[x1][y1][x2][y1] = IMPOS;
roads[x2][y1][x1][y1] = IMPOS;
}
}
/* 从西到东,修改无法通行道路 */
for(x1 = lake[i].x1 + 1; x1 < lake[i].x2; x1++){
for(y1 = lake[i].y1; y1 < lake[i].y2; y1++){
y2 = y1 + 1;
roads[x1][y1][x1][y2] = IMPOS;
roads[x1][y2][x1][y1] = IMPOS;
}
}
}
}
/* 移动当前位置,并返回通过时间 */
int move_next(int x, int y, int dir){
switch(dir){
case NORTH:
if(y - 1 > 0){
return roads[x][y][x][y - 1];
}
return IMPOS;
case SOUTH:
if(y + 1 <= m){
return roads[x][y][x][y + 1];
}
return IMPOS;
case WEST:
if(x - 1 > 0){
return roads[x][y][x - 1][y];
}
return IMPOS;
case EAST:
if(x + 1 <= n){
return roads[x][y][x + 1][y];
}
return IMPOS;
default:
return IMPOS;
}
}
/* floyd 求解最优路径 */
void floyd(){
int t, w;
crossing now, to;
int dir;
int nt;
/* 初始化距离 */
int x, y;
for(x = 1; x <= n; x++){
for(y = 1; y <= m; y++){
dis[x][y] = MAXTIME;
inq[x][y] = 0;
}
}
/* 将第一个点入队列 */
queue[0] = a;
inq[a.x][a.y] = 1;
dis[a.x][a.y] = 0;
t = 0;
w = 1;
while(t < w){
now = queue[t];
t++;
/* 检测当前点的邻接点 */
for(dir = 0; dir < 4; dir++){
if(IMPOS != (nt = move_next(now.x, now.y, dir))){
to.x = now.x + posx[dir];
to.y = now.y + posy[dir];
if(nt + dis[now.x][now.y] < dis[to.x][to.y]){
dis[to.x][to.y] = nt + dis[now.x][now.y];
if(0 == inq[to.x][to.y]){
queue[w] = to;
w++;
}
}
}
}
inq[now.x][now.y] = 0;
}
}
/* 主函数入口 */
int main(int argc, char *argv[]) {
int x1, y1, x2, y2; /* 索引值 */
int i;
#ifdef DEBUG
FILE *fp;
if(NULL == (fp = fopen("data.txt", "r"))){
return 1;
}
#endif
/* 获取尺寸,无法通行道路和湖泊数 */
#ifdef DEBUG
fscanf(fp, "%d %d %d %d", &n, &m, &t, &k);
#else
scanf("%d %d %d %d", &n, &m, &t, &k);
#endif
/* 横向通行时间 */
for(i = 1; i <= n; i++){
#ifdef DEBUG
fscanf(fp, "%d", &an[i]);
#else
scanf("%d", &an[i]);
#endif
}
/* 纵向通行时间 */
for(i = 1; i <= m; i++){
#ifdef DEBUG
fscanf(fp, "%d", &bm[i]);
#else
scanf("%d", &bm[i]);
#endif
}
/* 获取湖泊边界 */
for(i = 1; i <= k; i++){
#ifdef DEBUG
fscanf(fp, "%d %d %d %d", &lake[i].x1, &lake[i].x2, &lake[i].y1, &lake[i].y2);
#else
scanf("%d %d %d %d", &lake[i].x1, &lake[i].x2, &lake[i].y1, &lake[i].y2);
#endif
}
/* 获取无法通行道路 */
for(i = 1; i <= t; i++){
#ifdef DEBUG
fscanf(fp, "%d %d %d %d", &traffic[i].x1, &traffic[i].y1, &traffic[i].x2, &traffic[i].y2);
#else
scanf("%d %d %d %d", &traffic[i].x1, &traffic[i].y1, &traffic[i].x2, &traffic[i].y2);
#endif
}
/* 获取小松所在路口和图书馆位置 */
#ifdef DEBUG
fscanf(fp, "%d %d %d %d", &a.x, &a.y, &b.x, &b.y);
#else
scanf("%d %d %d %d", &a.x, &a.y, &b.x, &b.y);
#endif
/* 构建道路 */
draw_roads();
/* floyd 求最优路径 */
floyd();
/* 输出结果 */
printf("%d", dis[b.x][b.y]) ;
#ifdef DEBUG
fclose(fp);
#endif
return 0;
}