求最短图径算法。

tidycc 2013-01-09 11:07:31
所用的图如图所示


任意输入8条不可通过的纵线(如图中有蓝色线的地方)某一点开始,到另一点结束的最短路径算法,
1:路径最短。(每个纵线和横线的距离都是1)
2:在满足条件一的情况下,转弯次数最少。
3:也可能有多种路线结果一样,给出任意一结果即可。

输出结果:起点、多个转弯点和终点,若不经转弯直达,直接输出终点

举例如下:
从A(12,1)到B(6,5),不可通过的8条纵线是(11,1)(11,2)、 (12,1)(12,2)、
(10,3)(10,4)、(11,3)(11,4)、(6,1)(6,2)、(7,1)(7,2)、
(6,4)(6,5)、(7,4)(7,5)。也就是图中蓝色线条所在
输出结果例子
1: (12,1)(9,1) (9,5) (6,5)
2: (12,1) (8,1) (8,5) (6,5)
两个输出结果任输出任意一个即可。

要求编程语言:C

说明:不可通过的线只有纵线,没有横线,只有8条,没有更多,8条纵线随机放置。
此贴最高分只有100分,若有结果,再开送分贴,保证300分。
...全文
323 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
shuyecy 2013-03-23
  • 打赏
  • 举报
回复
引用 5 楼 amoyman 的回复:
用广度优先,咻地一下就算好了。 按照要求编程语言为C 执行结果是: (12, 1, 0, 0) --> ( 8, 1, 4, 1) --> ( 8, 5, 8, 2) --> ( 6, 5, 10, 3) 按回车结束 ... 代码如下: C/C++ code?12345678910111213141516171819……
没看出具体算法是什么。如果没有转弯数最少的要求就是直接BFS了(指访问过的点不扩展),有了这个要求状态空间加一个维度吧(访问到此用的转弯数)。其实这里只要从到这个点的最少转弯数扩展就行了。
tidycc 2013-03-19
  • 打赏
  • 举报
回复
我以为无人可以回答,所以很长时间没上来了,今天上来一看,很高兴有了答案,现结题,给分,全部给amoyman
阿麦 2013-01-28
  • 打赏
  • 举报
回复
用广度优先,咻地一下就算好了。 按照要求编程语言为C 执行结果是: (12, 1, 0, 0) --> ( 8, 1, 4, 1) --> ( 8, 5, 8, 2) --> ( 6, 5, 10, 3) 按回车结束 ... 代码如下:

#include <stdio.h>
#include <malloc.h>

typedef struct _NODE
{
	struct _NODE* Next[4];
	struct _NODE* Prev;
	int x;
	int y;
	int Distance;
	int Corner;
	int Flag; // 0-未处理, 1-待延伸, 2-新增加, 3-已处理
} NODE;

void Discover(NODE* Node, int Len)
{
	bool Exchange = true;
	while (Exchange)
	{
		for (int i = 0; i < Len; ++i)
		{
			if (Node[i].Flag == 1)
			{
				for (int f = 0; f < 4; ++f)
				{
					int Distance = Node[i].Distance;
					int Corner = Node[i].Corner + 1;
					NODE* p = &Node[i];
					while (p->Next[f] != NULL)
					{
						p = p->Next[f];
						++Distance;
						if (p->Flag == 0 || p->Distance > Distance || (p->Distance == Distance && p->Corner > Corner))
						{
							p->Prev = &Node[i];
							p->Corner = Corner;
							p->Distance = Distance;
							p->Flag = 2;
							Exchange = true;
						}
					}
				}
				Node[i].Flag = 3;
			}
		}
		Exchange = false;
		for (int i = 0; i < Len; ++i)
		{
			if (Node[i].Flag == 2)
			{
				Node[i].Flag = 1;
				Exchange = true;
			}
		}
	}
}

int main()
{
	int Width = 13; //图中横向的点数
	int Height = 5; // 图中纵向的点数
	// Cut 是从图中删除的线条:坐标x, 坐标y, 方向(0-Right,1-Up,2-Left,3-Down)
	// 原题中是只有纵线不可通过,这里扩展到横、纵都允许。
	int Cut[8][3] = {{5,0,3},{6,0,3},{10,0,3},{11,0,3},{9,2,3},{10,2,3},{5,3,3},{6,3,3}};
	// Start 是起点坐标(x, y)
	int Start[2] = {11, 0};
	// Final 是终点坐标(x, y)
	int Final[2] = {5, 4};

	// 根据条件,初始化环境
	NODE* Node = (NODE*)malloc(sizeof(NODE) * Height * Width);
	for (int y = 0; y < Height; ++y)
	{
		int base = y * Width;
		for (int x = 0; x < Width; ++x)
		{
			Node[base + x].Corner = 0;
			Node[base + x].Distance = 0x10000;
			Node[base + x].Flag = 0;
			Node[base + x].Prev = NULL;
			Node[base + x].x = x + 1;
			Node[base + x].y = y + 1;
			Node[base + x].Next[0] = x < Width - 1 ? &Node[base + x + 1] : NULL;
			Node[base + x].Next[1] = y > 0 ? &Node[base + x - Width] : NULL;
			Node[base + x].Next[2] = x > 0 ? &Node[base + x - 1] : NULL;
			Node[base + x].Next[3] = y < Height - 1 ? &Node[base + x + Width] : NULL;
		}
	}
	for (int i = 0; i < 8; ++i)
	{
		Node[Cut[i][1] * Width + Cut[i][0]].Next[Cut[i][2]]->Next[3 - Cut[i][2]] = NULL;
		Node[Cut[i][1] * Width + Cut[i][0]].Next[Cut[i][2]] = NULL;
	}

	// 定义起点,并进行搜索
	NODE* pStart = &Node[Start[1] * Width + Start[0]];
	pStart->Distance = 0;
	pStart->Flag = 1;
	Discover(Node, Width * Height);

	// 输出
	NODE* Stack[100];
	int Index = 0;
	NODE* p = &Node[Final[1] * Width + Final[0]];
	while (p->Distance > 0)
	{
		Stack[Index++] = p;
		p = p->Prev;
	}
	printf_s("    (%2d, %2d, %2d, %2d)\n", p->x, p->y, p->Distance, p->Corner);
	while (Index > 0)
	{
		p = Stack[--Index];
		printf_s("--> (%2d, %2d, %2d, %2d)\n", p->x, p->y, p->Distance, p->Corner);
	}
	free(Node);

	printf_s("按回车结束 ...");
	getchar();

	return 0;
}
tidycc 2013-01-27
  • 打赏
  • 举报
回复
人工置下顶,看还有没有高手帮忙
sosidami 2013-01-11
  • 打赏
  • 举报
回复

/**
  Dijkstra algorithm Single Source Shortest path

next : cluster according to the begin point of the edge.
head[]: the first edge of begin with _;
Time complexity O(ElogV)
 */

#include <iostream> 
#include <vector>
#include <algorithm>
#include <queue>
#include <string.h>
#include <stdio.h>
using namespace std;

#define V   100
#define E   1000
#define INF 329999         

// v :the end point of an edge. w : the weight of the weight next:cluster according to the begin point of the edge
struct node
{
    int v, w,next;
    node(int vv=0, int ww=0):v(vv),w(ww){}
    bool operator < (const node& r) const{return w> r.w;}
}pnt[E];

int e=0,N,M;

int head[V];
int dis[V];
bool vis[V];
int src, sink;

void Dijkstra()
{ 
    priority_queue<node> Q; 
    vis[src] = 1; dis[src] = 0; 
    Q.push(node(src, 0)); 
    for (int u = src, i=1; i< N; i++)                 
    { 
        for (int j = head[u]; j != -1; j = pnt[j].next)    // j is edge number.
        { 
            int v = pnt[j].v;                          
            if (vis[v] == 0 && dis[v] > dis[u] + pnt[j].w )// pre is the current vertex
            { 
                dis[v] = dis[u] + pnt[j].w; 
                Q.push(node(v, dis[v]));
            } 
        } 
        while (!Q.empty() && vis[Q.top().v]) Q.pop(); 
        if (Q.empty()) break;
        vis[u = Q.top().v] = 1; Q.pop();
    }
} 

inline void addedge(int u, int v, int w){ 
    pnt[e].v = v; pnt[e].w = w; pnt[e].next= head[u]; head[u]=e++;
} 

void Dijkstra_init()
{ 
    e = 0; 
    memset(head, -1, sizeof(head)); 
    memset(vis, 0, sizeof(vis)); 
    for (int i = 0; i < N; i++) dis[i] = INF; 
    addedge(0,2,1);
    addedge(2,0,1);
    addedge(0,1,4);
    addedge(1,0,4);
    addedge(1,3,1);
    addedge(3,1,1);
    addedge(2,3,4);
    addedge(3,2,4);
    addedge(2,4,2);
    addedge(4,2,2);
    addedge(3,5,2);
    addedge(6,3,2);
    addedge(4,5,3);
    addedge(5,4,3); 
} 

int main()
{

    N= 6, M=7;
    src =0; 
    Dijkstra_init();
    Dijkstra();
    return 0;
}
这个是之前写的优先队列优化的Dijkstra,你照着改一下吧。在node中加相关属性,松弛条件改一下就OK。
tidycc 2013-01-11
  • 打赏
  • 举报
回复
引用 1 楼 sosidami 的回复:
用Dijkstra 就可以的,每一个点有一个距离属性,有一个转弯多少属性,有前一个最短路点。松弛条件是 先比较距离,然后比较转弯数,更具前一个最短路点更新当前点的转弯多少属性。 因为你不可穿过的线段其实是图中不可经过的边。
求C代码 或例子。
sosidami 2013-01-10
  • 打赏
  • 举报
回复
用Dijkstra 就可以的,每一个点有一个距离属性,有一个转弯多少属性,有前一个最短路点。松弛条件是 先比较距离,然后比较转弯数,更具前一个最短路点更新当前点的转弯多少属性。 因为你不可穿过的线段其实是图中不可经过的边。

33,010

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧