CODE[VS]1024 一塔湖图

题目: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;
}

猜你喜欢

转载自blog.csdn.net/QQ604666459/article/details/77985977