图 -> BFS

本文介绍了一个基于图论的BFS(广度优先搜索)算法实现案例,通过解决一个具体的迷宫寻路问题来展示BFS算法的应用。代码中详细展示了如何利用C++实现节点结构、状态转移和路径回溯等功能。



图论-  BFS


Abbott的复仇


#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;

struct Node {
  int r, c, dir; // 站在(r,c),面朝方向dir(0~3分别表示N, E, S, W)
  Node(int r=0, int c=0, int dir=0):r(r),c(c),dir(dir) {}
};

const int maxn = 10;
const char* dirs = "NESW"; // 顺时针旋转  North East South West
const char* turns = "FLR"; // 向前 左 右

int has_edge[maxn][maxn][4][3];
int d[maxn][maxn][4];
Node p[maxn][maxn][4];
int r0, c0, dir, r1, c1, r2, c2;

int dir_id(char c) { return strchr(dirs, c) - dirs; }
int turn_id(char c) { return strchr(turns, c) - turns; }

const int dr[] = {-1, 0, 1, 0};
const int dc[] = {0, 1, 0, -1};

Node walk(const Node& u, int turn) {
  int dir = u.dir;
  if(turn == 1) dir = (dir + 3) % 4; // 逆时针
  if(turn == 2) dir = (dir + 1) % 4; // 顺时针
  return Node(u.r + dr[dir], u.c + dc[dir], dir);
}

bool inside(int r, int c) {
  return r >= 1 && r <= 9 && c >= 1 && c <= 9;
}

bool read_case() {
  char s[99], s2[99];
  if(scanf("%s%d%d%s%d%d", s, &r0, &c0, s2, &r2, &c2) != 6) return false;
  printf("%s\n", s);

  dir = dir_id(s2[0]);
  r1 = r0 + dr[dir];
  c1 = c0 + dc[dir];

  memset(has_edge, 0, sizeof(has_edge));
  for(;;) {
    int r, c;
    scanf("%d", &r);
    if(r == 0) break;
    scanf("%d", &c);
    while(scanf("%s", s) == 1 && s[0] != '*') {
      for(int i = 1; i < strlen(s); i++)
        has_edge[r][c][dir_id(s[0])][turn_id(s[i])] = 1;
    }
  }
  return true;
}

void print_ans(Node u) {
  // 从目标结点逆序追溯到初始结点
  vector<Node> nodes;
  for(;;) {
    nodes.push_back(u);
    if(d[u.r][u.c][u.dir] == 0) break;
    u = p[u.r][u.c][u.dir];
  }
  nodes.push_back(Node(r0, c0, dir));

  // 打印解,每行10个
  int cnt = 0;
  for(int i = nodes.size()-1; i >= 0; i--) {
    if(cnt % 10 == 0) printf(" ");
    printf(" (%d,%d)", nodes[i].r, nodes[i].c);
    if(++cnt % 10 == 0) printf("\n");
  }
  if(nodes.size() % 10 != 0) printf("\n");
}

void solve() {
  queue<Node> q;
  memset(d, -1, sizeof(d));
  Node u(r1, c1, dir);
  d[u.r][u.c][u.dir] = 0;
  q.push(u);
  while(!q.empty()) {
    Node u = q.front(); q.pop();
    if(u.r == r2 && u.c == c2) { print_ans(u); return; }
    for(int i = 0; i < 3; i++) {
      Node v = walk(u, i);
      if(has_edge[u.r][u.c][u.dir][i] && inside(v.r, v.c) && d[v.r][v.c][v.dir] < 0) {
        d[v.r][v.c][v.dir] = d[u.r][u.c][u.dir] + 1;
        p[v.r][v.c][v.dir] = u;
        q.push(v);
      }
    }
  }
  printf("  No Solution Possible\n");
}

int main() {
  while(read_case()) {
    solve();
  }
  return 0;
}

11 12 11

21 22 23

31 33


物联网通信协议测试是保障各类设备间实现可靠数据交互的核心环节。在众多适用于物联网的通信协议中,MQTT(消息队列遥测传输)以其设计简洁与低能耗的优势,获得了广泛应用。为确保MQTT客户端与服务端的实现严格遵循既定标准,并具备良好的互操作性,实施系统化的测试验证至关重要。 为此,采用TTCN-3(树表结合表示法第3版)这一国际标准化测试语言构建的自动化测试框架被引入。该语言擅长表达复杂的测试逻辑与数据结构,同时保持了代码的清晰度与可维护性。基于此框架开发的MQTT协议一致性验证套件,旨在自动化地检验MQTT实现是否完全符合协议规范,并验证其与Eclipse基金会及欧洲电信标准化协会(ETSI)所发布的相关标准的兼容性。这两个组织在物联网通信领域具有广泛影响力,其标准常被视为行业重要参考。 MQTT协议本身存在多个迭代版本,例如3.1、3.1.1以及功能更为丰富的5.0版。一套完备的测试工具必须能够覆盖对这些不同版本的验证,以确保基于各版本开发的设备与应用均能满足一致的质量与可靠性要求,这对于物联网生态的长期稳定运行具有基础性意义。 本资源包内包含核心测试框架文件、一份概述性介绍文档以及一份附加资源文档。这些材料共同提供了关于测试套件功能、应用方法及可能包含的扩展工具或示例的详细信息,旨在协助用户快速理解并部署该测试解决方案。 综上所述,一个基于TTCN-3的高效自动化测试框架,为执行全面、标准的MQTT协议一致性验证提供了理想的技术路径。通过此类专业测试套件,开发人员能够有效确保其MQTT实现的规范符合性与系统兼容性,从而为构建稳定、安全的物联网通信环境奠定坚实基础。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
#include <stdio.h> #include <stdlib.h> #include <ctype.h> #define N 1001 typedef struct Queue{ int data[N]; int front,rear; } Queue; void InitQueue(Queue *q){ q->front = q->rear = 0; } void EnQueue(Queue *q,int x){ q->data[q->rear++]=x; } int DeQueue(Queue *q){ return q->data[q->front++]; } int IsEmptyQueue(Queue *q){ return q->front == q->rear; } typedef struct node { int adjvex; struct node *next; } EdgeNode; typedef struct { char vertex; EdgeNode *link; } VexNode; typedef struct { VexNode adjlist[N]; int n,m; } Graph; void InitGraph(Graph *G,int n){ G->n=n; G->m=0; for (int i=1;i<=n;i++){ G->adjlist[i].vertex='0'+i; G->adjlist[i].link=NULL; } } void creatAdjList(Graph *G){ int i,j,k; EdgeNode *s; scanf("%d",&G->m); for (k=1;k<=G->n;k++){ scanf("%d %d",&i,&j); s=(EdgeNode*)malloc(sizeof(EdgeNode)); s->adjvex=j; s->next=G->adjlist[i].link; G->adjlist[i].link=s; s=(EdgeNode*)malloc(sizeof(EdgeNode)); s->adjvex=i; s->next=G->adjlist[j].link; G->adjlist[j].link=s; } } int BFS(Graph *G,int start){ int visited[N]={0}; int dist[N]={0}; Queue q; InitQueue(&q); visited[start]=1; EnQueue(&q,start); int count=1; while (!IsEmptyQueue(&q)) { int y=DeQueue(&q); EdgeNode *p=G->adjlist[y].link; while (p!=NULL) { int z=p->adjvex; if (!visited[z]) { visited[z]=1; dist[z]=dist[y]+1; if (dist[z]<=6) { count++; EnQueue(&q,z); } } p = p->next; } } return count; } int main(){ int n; Graph G; scanf("%d",&n); InitGraph(&G,n); creatAdjList(&G); for (int i=1;i<=n;i++){ int a=BFS(&G,i); double b=(a*100.0)/n; printf("%d: %.2f%%\n",i,b); } return 0; } 根据片结果修改代码
11-29
```markdown ## 题目重述 根据提供的代码和评测结果,程序实现的是基于邻接表的无向构建与广度优先搜索(BFS),用于计算从每个顶点出发在6层以内能到达的顶点比例(社交网络“六度空间”问题)。但提交后**部分测试点答案错误**,尤其是“最大N和M”测试点失败。 目标是:**根据评测反馈修改代码,使其通过所有测试用例。** --- ## 给出答案(答案为带注释的代码块) ```c #include <stdio.h> #include <stdlib.h> #include <ctype.h> #define N 1001 typedef struct Queue { int data[N]; int front, rear; } Queue; void InitQueue(Queue *q) { q->front = q->rear = 0; } void EnQueue(Queue *q, int x) { q->data[q->rear++] = x; } int DeQueue(Queue *q) { return q->data[q->front++]; } int IsEmptyQueue(Queue *q) { return q->front == q->rear; } typedef struct node { int adjvex; struct node *next; } EdgeNode; typedef struct { char vertex; EdgeNode *link; } VexNode; typedef struct { VexNode adjlist[N]; int n, m; } Graph; void InitGraph(Graph *G, int n) { G->n = n; G->m = 0; for (int i = 1; i <= n; i++) { G->adjlist[i].vertex = '0' + i; G->adjlist[i].link = NULL; } } // 修改点1:输入边数应为 G->m,但循环次数却是 G->n // 原函数使用了 k <= G->n,这是错误的!应该读取 m 条边 void creatAdjList(Graph *G) { int i, j; EdgeNode *s; scanf("%d", &G->m); // 修改:循环 m 次,而不是 n 次 for (int k = 0; k < G->m; k++) { // 原来是 k<=G->n 错误! scanf("%d %d", &i, &j); // 添加边 i->j s = (EdgeNode*)malloc(sizeof(EdgeNode)); s->adjvex = j; s->next = G->adjlist[i].link; G->adjlist[i].link = s; // 添加边 j->i(无向) s = (EdgeNode*)malloc(sizeof(EdgeNode)); s->adjvex = i; s->next = G->adjlist[j].link; G->adjlist[j].link = s; } } // 修改点2:BFS 中距离判断逻辑优化,避免无效入队 int BFS(Graph *G, int start) { int visited[N] = {0}; int dist[N] = {0}; // 初始化为0 Queue q; InitQueue(&q); visited[start] = 1; EnQueue(&q, start); int count = 1; // 包含起点本身 while (!IsEmptyQueue(&q)) { int y = DeQueue(&q); EdgeNode *p = G->adjlist[y].link; while (p != NULL) { int z = p->adjvex; if (!visited[z]) { visited[z] = 1; dist[z] = dist[y] + 1; // 只有距离 ≤ 6 才计入并继续扩展 if (dist[z] <= 6) { count++; EnQueue(&q, z); } // 注意:即使 dist[z] > 6,也不入队(已隐式处理) } p = p->next; } } return count; } int main() { int n; Graph G; scanf("%d", &n); InitGraph(&G, n); creatAdjList(&G); // 构建邻接表 for (int i = 1; i <= n; i++) { int a = BFS(&G, i); double b = (a * 100.0) / n; printf("%d: %.2f%%\n", i, b); } return 0; } ``` --- ## 代码解析 1. **`creatAdjList` 函数原错误**: - 原代码中 `for(k=1; k<=G->n; k++)` 表示循环 $ n $ 次,但实际上应读取 $ m $ 条边。 - 导致当 $ m \ne n $ 时(如稀疏或稠密),会多读或少读边,造成建错误。 - **修正为 `for(int k=0; k<G->m; k++)`**,确保只读取 $ m $ 条边。 2. **输入顺序问题**: - 原始调用 `scanf("%d",&G->m);` 正确获取边数,但后续却未使用它控制循环,导致逻辑错乱。 3. **BFS 距离控制合理**: - 当前 BFS 实现已正确设置 `dist[z] = dist[y]+1`,并在 `dist[z] <= 6` 时才计数和入队,防止超过6层传播。 - 此部分逻辑无需大改,仅微调即可。 4. **内存与初始化安全**: - 使用局部数组 `visited[N]`, `dist[N]` 并初始化为0,符合规范。 - 队列操作封装良好,无越界风险(因最多 $ N $ 个节点)。 5. **输出格式正确**: - 输出形如 `i: xx.xx%`,使用 `%.2f%%` 正确保留两位小数并输出百分号。 --- ## 知识点(列出该代码中遇到的知识点) - **邻接表建**:用链表存储每个顶点的邻接点,适合稀疏,插入双向边实现无向- **广度优先搜索(BFS)**:按层遍历,记录距离,用于求最短路径或可达范围。 - **六度空间理论模拟**:限制BFS深度为6,统计传播覆盖人数,体现社会网络特性。 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值