zoukankan      html  css  js  c++  java
  • Emergency【PAT 1003题】图的非递归深度优先搜索

    题目链接: http://pat.zju.edu.cn/contests/pat-practise/1003

    这道题目是让求图中两节点之间的最短路径条数,同时求出这些最短路径中权值相加最大值,可以通过修改Dijkstra算法解题,不过我用的是深度优先搜索,书上总是说递归的程序比非递归程序容易看懂,而且逻辑也符合正常思维方式,可我却对递归结构很不感冒,确实,递归随随便便5行代码,可能用栈需要20+行才能模拟出来,但是我还是偏好于非递归实现,至少我觉得这个符合自己的思维习惯,话说回来,不用DJ,而采用深搜解这道题,也是因为深搜更容易想到而且能够想通,毕竟,暴力是蛮荒时代的本色,而能想出巧力的头脑都是苹果砸出来的。

    深搜的思路是:从start结点出发,采用深度优先搜索方式,遍历整个图,记录下start到end的所有路径,只要遇到end结点,就认为这条深搜路径完成,将cost和saveTeam两个结果存至road中,然后回溯到上一个结点,继续深搜,以寻找其它能够到达end的路径,当把所有可能的路径寻找完以后(注意:所有的路径都是简单路径,不能存在环),将road按照cost大小进行排序,数出cost最小的相同值有几个,同时在这些cost相同的前提下,找到saveTeam的最大值,将这两个值数出,即为题目所求。

      1 /*使用深度优先搜索,如果搜索到目的结点,则回溯至上一个结点重新深度优先搜索*/
    2 #include <stdio.h>
    3 #include <stdlib.h>
    4
    5 typedef struct
    6 {
    7 int cost;//该条路径的长度
    8 int number;//该条路径可以召集的救援组数目
    9 }route;//结果的结构体,记录两节点之间的所有路径
    10
    11 typedef struct
    12 {
    13 int top;
    14 int data[501];
    15 }stk;
    16
    17 int edge[501][501];//邻接矩阵
    18 route road[1000];//假设start和end之间最多有1000条不相同路径
    19
    20 int comp(const void *a, const void *b)
    21 {
    22 route c = *(route *)a;
    23 route d = *(route *)b;
    24 if(c.cost > d.cost) return 1;
    25 else return -1;
    26 }
    27
    28 int main()
    29 {
    30 int n;//城市数目
    31 int m;//道路数目
    32 int start;//当前所在城市
    33 int end;//需要救援的城市
    34 int *saveTeam;//每个城市的救援组数目
    35 int pos;//road数组的游标
    36 int tempcost, tempnumber;//cost和number两个变量的临时版本
    37 int prenode;//dfs搜索时记录最近一次向下深搜的结点
    38
    39 int sum,max;
    40
    41 int i, j;
    42 int c1, c2, l;
    43 int final[501];
    44 stk entry;//深搜栈
    45 int k, t;
    46
    47 while(scanf("%d %d %d %d", &n, &m, &start, &end) != EOF)
    48 {
    49 for(i = 0; i < 501; i ++)
    50 {
    51 for(j = 0; j < 501; j ++)
    52 {
    53 edge[i][j] = 0;
    54 }
    55 }
    56 saveTeam = (int *)malloc(n * sizeof(int));
    57 for(i = 0; i < n; i ++)
    58 {
    59 scanf("%d", &saveTeam[i]);
    60 }
    61 for(i = 0; i < m; i ++)
    62 {
    63 scanf("%d %d %d", &c1, &c2, &l);
    64 edge[c1][c2] = l;
    65 edge[c2][c1] = l;
    66 }
    67 for(i = 0; i < n; i ++)
    68 {
    69 final[i] = 0;//都未访问
    70 }
    71 entry.top = 0;
    72 entry.data[entry.top] = start;//源点入栈
    73 entry.top ++;
    74 final[start] = 1;
    75 pos = 0;
    76 tempcost = 0;
    77 tempnumber = saveTeam[start];
    78 prenode = -1;
    79 while(entry.top != 0)
    80 {
    81 k = entry.data[entry.top - 1];
    82 if(k == end)//队长现在在的城市就是需要救援的城市,即start == end,这个if块不加上会导致第二个案例WA
    83 {
    84 road[pos].cost = 0;
    85 road[pos].number = saveTeam[k];
    86 pos ++;
    87 entry.top --;
    88 continue;
    89 }
    90 for(i = prenode + 1; i < n; i ++)
    91 {
    92 if(final[i] == 0 && edge[k][i] != 0)
    93 {
    94 break;
    95 }
    96 }
    97 if(i < n)//找到了向下深搜的结点
    98 {
    99 tempcost += edge[k][i];
    100 tempnumber += saveTeam[i];
    101 if(i == end)//该点是深搜的终点
    102 {
    103 road[pos].cost = tempcost;
    104 road[pos].number = tempnumber;
    105 pos ++;
    106 //printf("pos = %d, cost = %d, number = %d\n",pos - 1, road[pos - 1].cost, road[pos - 1].number);
    107 tempcost -= edge[k][i];
    108 tempnumber -= saveTeam[i];//因为回溯到了上一个结点,所以要减去
    109 prenode = i;
    110 }
    111 else//该点只是一个普通结点
    112 {
    113 entry.data[entry.top] = i;
    114 entry.top ++;
    115 final[i] = 1;
    116 prenode = -1;
    117 }
    118 }
    119 else//没有找到向下深搜的结点,需要回溯
    120 {
    121 t = entry.data[entry.top - 2];
    122 tempcost -= edge[t][k];
    123 tempnumber -= saveTeam[k];
    124 prenode = k;
    125 final[k] = 0;
    126 entry.top --;
    127 }
    128 }
    129 qsort(road, pos, sizeof(route), comp);
    130 sum = 0;
    131 max = 0;
    132 for(i = 0; i < pos; i ++)
    133 {
    134 if(road[i].cost == road[0].cost)
    135 {
    136 sum ++;
    137 if(road[i].number > max)
    138 {
    139 max = road[i].number;
    140 }
    141 }
    142 else
    143 {
    144 break;
    145 }
    146 }
    147 printf("%d %d\n",sum, max);
    148
    149 }
    150 return 0;
    151 }



  • 相关阅读:
    mysql执行update报错 Err] 1055
    scp从远程指定目录拷贝文件到本地指定目录
    内存溢出
    BlockingQueue-----多线程(一)
    版主
    Mybatis学习总结-----mybatis中refid是什么意思(十)
    Mybatis学习总结--------Mybatis <where>标签 (九)
    @RequestMapping 和 @GetMapping @PostMapping 区别
    @RequiresPermissions ,@RequiresUser , @RequiresGuest ,@RequiresRoles 解释
    response.setHeader的各种用法 ------ 笔记(一)
  • 原文地址:https://www.cnblogs.com/Rafy/p/2399832.html
Copyright © 2011-2022 走看看