`
dlzjp123
  • 浏览: 23810 次
  • 性别: Icon_minigender_1
  • 来自: 大连
文章分类
社区版块
存档分类
最新评论

一笔画问题的c++实现

阅读更多

一笔画问题,即欧拉回路问题,最近在算法课上老师留了这个作业,下面将我的实现说一下。首先,先将问题描述一下。

该图中节点编号从上至下,从左至右编号如下
  1   2
3 4 5 6
7 8 9 10 11
   12 13
  14 15 16
要求:从节点1开始,一笔将该图形画出。
首先讲下该题的大概思路:
概括的讲是先找小回路,再并小回路。
(1)先将1放入访问队列中,寻找1的未访问过的邻接边,将满足这样条件的边中另一顶点值最小的顶点放入访问队列中,再从这个点出发继续寻找,直至找到的变的另一顶点与队列头部顶点相等(这时说明找到了一条小回路),将找到的第一个小回路的边标记为1;若队列头顶点还存在另一小回路,则继续寻找另一小回路;否则要将队列头结点删除,开始下一点的查找。
(2)将图中所有边都标记后,再从1开始,找与该点邻接的边中值最大的边的另一点,若存在多个边值一样的边,则先从顶点值较小的点开始,并将当前访问的点设置为该点,再往下找。
说了这么多,还是感觉不大明白。用本题的具体数字说明一下。
第一次找小回路1-3-4-1
第二次3-7-8-3
第三次4-8-9-4
第四次9-5-2-6-5-10-6-11-10-9
。。。。。。
在访问队列中存储的节点
1,3,4,7,8,9,5,2,6,10,11,12,13,14,15,16
#include<queue>
#include<iostream>
#include<fstream>
#include<string>
#define MAX 1000
using namespace std;
int main(){
	ifstream fin("input2.txt");
	ofstream fout("output.txt");
	int m,n,start,end;
	int i,j;
	int now,front;
	int flag = 1;//边的标记
	int count = 2;
	int cycleSt = 1;//一笔画的起点
	int cycleEnd = 1;//一笔画的终点
	int minNode=9999;
	int maxEdge = 0;
	fin>>m>>n;//m:图中点数,n:输入文件数据行数
	int **edge = new int*[m+1];//图的连通二维数组表示
	for(i=0;i<m+1;i++)
		edge[i] = new int[m+1];
	bool *inQueue = new bool[m+1];//图中顶点的访问队列标记,
	//若之前该顶点已放入队列中,那么该顶点标记为true
	//若该顶点从未放入队列中,那么该顶点标记为false
	for(i=1;i<m+1;i++)
		inQueue[i]=false;
	//初始化连通图,值为MAX则说明未连通
	for(i=0;i<m+1;i++)
		for(j=0;j<m+1;j++)
			edge[i][j]=MAX;
	queue<int> q;//顶点访问队列
	fin>>start>>end;
	q.push(start);//先将起始点放入访问队列中
	edge[end][start]=edge[start][end]=0;
	while(count<=n){
		fin>>start>>end;
		edge[start][end]=edge[end][start]=0;
		count++;
	}
	front = q.front();//小回路的起点
	now = q.front();//目前正在访问的点
	inQueue[now]=true;//把起点标记为true,表示已放入过队列
	do{
		for(i=1;i<m+1;i++){
			if(edge[now][i]==0){//如果与起点邻接的某边未走过
				edge[i][now]=edge[now][i]=flag;//标记该边
				if(i!=front&&!inQueue[i]){
					q.push(i);//把与该边邻接的另一顶点放入队列
					inQueue[i] = true;//将该点放入过队列的标记设置为true
				}
				now = i;//下一步开始从这一点出发
				break;
			}
		}
		if(i==m+1){//如果某个点相邻接的边都访问过,那么将该点从访问队列中删除,并访问下一个点
			cout<<front<<" ";
			q.pop();
			if(!q.empty()){
				now = q.front();
				front = q.front();
			}
		}
		else if(now==front){//如果现在访问的点是小回路的起点
			//首先查看该回路是否有其他的回路存在
			for(i=1;i<m+1;i++){
				if(edge[now][i]==0)break;
			}
			//没有其他未访问的边了,删除头结点,访问下一结点,并将边标记加1
			if(i==m+1){
				cout<<front<<" ";
				q.pop();
				if(!q.empty()){
					now=q.front();
					inQueue[now]=true;
					front = q.front();
				}
				flag++;
			}else{//若还有其他未访问的边,则将边标记加1后,走新的小回路
				now = front;
				flag++;
			}
		}
	}while(!q.empty());
	/*for(i=1;i<m+1;i++)
		for(j=1;j<m+1;j++)
			fout<<edge[i][j]<<" ";
		fout<<endl;*/
	now = cycleSt;
	cout<<"一笔画的路线是:"<<endl<<now<<"->";
	while(true){
		maxEdge = 0;
		minNode = 9999;
		for(i=1;i<m+1;i++){
			//在边标记不同的情况下,找表标记最大的边的邻接点
			//在边标记相同的情况下,找节点值最小的邻接点
			if(edge[now][i]>maxEdge&&edge[now][i]!=MAX){
				maxEdge = edge[now][i];
				//edge[i][now]=edge[now][i]=MAX;
				minNode = i;
				//break;
			}
		}
		if(minNode==9999){
			cout<<"未能找到一笔画路线"<<endl;
			break;
		}else{
		edge[minNode][now]=edge[now][minNode]=MAX;//访问后,将连通边设置为不连通
		now = minNode;
		if(now==cycleEnd) {cout<<now;break;}//如果起点和终点相等,则退出循环
		else cout<<now<<"->";
		}
	}
	return 0;
}

呵呵,讲的可能不是很清楚,有不懂的可以问我,希望大家可以在这探讨,源程序及输入文件见压缩包附件。
PS:感谢杨老师的算法课,这位老教授的课很有趣,我也收获了很多。
  • 大小: 9.1 KB
1
0
分享到:
评论
2 楼 绝缘君 2016-12-19  
博主的算法思路很棒......我运行不出是编译器的原因吗= =
1 楼 绝缘君 2016-12-19  
为啥代码运行不出来报错:0x746BA832 处(位于 Project1.exe 中)有未经处理的异常: Microsoft C++ 异常: std::bad_array_new_length,位于内存位置 0x006FF590 处。

相关推荐

    一笔画-C++游戏

    在这个特殊的实现中,游戏是使用C++编程语言编写的,并且结合了Microsoft Foundation Classes (MFC)库来构建用户界面。MFC是微软为Windows应用程序开发提供的一套C++类库,它简化了Windows API的使用。 在这款...

    一笔画问题

    一笔画问题,也被称为欧拉路径问题,是图论中...通过C++实现,我们可以利用面向对象编程的优势,将问题分解为独立的类和方法,使得代码易于理解和维护。在实际编程时,要注重代码的可读性和效率,遵循良好的编程规范。

    Qt一笔画小游戏源码,,,

    本项目基于Qt实现了一款一笔画游戏,这种游戏通常要求玩家在一张网格上用一笔连接所有的点,且不能重复经过任何线段。下面将详细解析该项目的源码和实现机制。 首先,我们来看项目的解决方案文件`OneStroke.sln`,...

    一笔画程序 OneTouchDraw

    一笔画游戏,也称为欧拉路径问题,是经典的逻辑谜题,玩家需要从起点开始,沿着图形的边,不重复任何边,最后回到起点,完成整个图形的绘制。这种游戏挑战了玩家的空间想象和逻辑思维能力,而在OneTouchDraw的帮助下...

    基本Qt的一笔画小游戏,,,

    在编程实现中,这通常涉及到图论中的连通性问题。开发者可能使用邻接矩阵或邻接表来表示游戏板,并通过深度优先搜索(DFS)或广度优先搜索(BFS)等算法来检查是否能一笔画完所有节点。 标签“Qt”再次强调了这款...

    小游戏源码-一笔画.rar

    4. **算法与数据结构**:解决一笔画问题可能需要用到图论中的算法,如深度优先搜索(DFS)或广度优先搜索(BFS),以及路径规划。 5. **事件处理**:游戏需要响应用户的触摸、点击等操作,这涉及事件监听和处理机制...

    C/C++程序员面试指南.杨国祥(带详细书签).pdf

    本书以流行的面试题讲解为主要内容,介绍了C、C++语言基本概念,包括保留字、字符串、指针和引用、结构体、库函数等各个方面的基础知识,介绍了面向对象编程基本概念,包括如何实现继承、多态和封装等。还介绍了排序...

    用VC一笔画金刚石,魔术三角和递归圆

    本文将深入探讨如何使用Visual C++(简称VC)来实现一笔画出金刚石、魔术三角和递归圆这三个有趣的图形。首先,我们要明白这涉及到的基本概念和编程技术。 **一笔画算法(一笔连通图)** 一笔画问题源于图论,指的...

    第十四周讨论课个人资料(ppt)1

    【算法实现】Hierholzer算法的C++实现包括一个dfs()函数,用于递归遍历图,以及主函数main()中读取图的输入并调用dfs()。这里使用了栈q来存储答案队列,确保了路径的正确输出。 总的来说,图论中的一笔画问题和相关...

    中国邮递员问题.pptx

    "中国邮递员问题" 中国邮递员问题(CPP)是一个著名的图论问题,旨在寻找一条可能短的路线,使邮递员从邮局出发,经过所有街道至少一次后返回邮局。这个问题是中国数学家管梅谷在1962年首先提出的。 问题描述 ...

    ACM算法集锦(实现代码)

    15. **其他题目**:包括排球队员站位问题、自然数分解问题、马的遍历、加法分式分解、地图着色、放置长条块、最短路径、火车调度、农夫过河、七段数码管问题、数字不连续问题、棋子移动问题、一笔画问题、城市遍历、...

    算法设计及分析习题答案解析1_6章.doc

    快速排序的伪代码和C++实现如下: ```cpp // 快速排序的分割函数 int partition(int arr[], int low, int high) { // ... } // 快速排序函数 void quickSort(int arr[], int low, int high) { // ... } // ...

    图形学实验

    在图形学中,我们可能使用编程语言如C++或Python,结合OpenGL或DirectX等图形库来实现这样的画法。通过设置合适的顶点坐标并绘制线条,我们可以创建出各种形状和尺寸的菱形。 其次,“奇数一笔画”是一个与图论和...

    部分外企笔试真题总结

    2. **一笔画问题**:这是典型的图论问题,要求寻找一笔画路径。对于特定的图形,可以通过观察和尝试找到解决方案。 3. **开关状态问题**:这个问题涉及到数学中的平方根的概念。最终处于关闭状态的灯是那些编号为...

    算法设计与分析习题答案1-6章.pdf

    C++实现如下: ```cpp int findClosestPair(int arr[], int n) { int min_diff = INT_MAX; int pair1 = 0, pair2 = 1; for (int i = 0; i ; i++) for (int j = i+1; j ; j++) if (abs(arr[i] - arr[j]) ) {...

    算法设计与分析习题答案1-6章.doc

    以下是C++实现: ```cpp void quicksort(int arr[], int low, int high); int partions(int arr[], int low, int high); int main(){ int a[] = {...}; int n = sizeof(a) / sizeof(a[0]); quicksort(a, 0, ...

    算法设计与分析习题解答1-6章.docx

    以下是C++实现: ```cpp #include void quicksort(int a[], int low, int high); int partions(int a[], int low, int high); int main() { int a[] = { ... }; // 初始化数组 int n = sizeof(a) / sizeof(a[0]...

    算法设计与分析习题答案1-6章 (2).pdf

    C++代码实现: ```cpp int main() { double value = 0; for (int n = 1; n ; ++n) { value = value * 10 + 1; if (value % 2013 == 0) { cout 至少为:" ; break; } } } ``` 5. **计算π值**:π值的...

    计算机图形学 金刚石

    在编程实现时,一般会选用一种高级图形库,如OpenGL、DirectX或更简单的2D图形库如pygame(Python)或GDI+(C++)。这些库提供了绘制线条、填充图形和设置颜色等功能。在我们的例子中,我们可能会选择一个简单的方法...

Global site tag (gtag.js) - Google Analytics