将图的顶点二维坐标转换为一维索引(图模型的建立)

参照leetcode 695题
给定一个二维数组,a[i][j] == 1 (无向图)即为顶点,该顶点的坐标为 (i,j)。注意这里给定的矩阵不是邻接矩阵,这个矩阵给出的信息是顶点的坐标位置。
在进行图的遍历时
1.若要直接使用该矩阵,则在遍历时,从一个顶点到下一个顶点的操作需要注意
2.可将该矩阵转换为邻接表,邻接表作为遍历时的数据结构我们比较熟悉。
下面介绍如何将这个矩阵转化为邻接表。
在这里插入图片描述
在C/C++中,二维数组实际上是两个一维数组拼接而成,矩阵中的每个点的坐标(r,c)(r为所在行号,c为所在列号)都可以转换为一维索引,设矩阵的行数为R,列数为C,则(x,y)对应的一维索引为 rC+c 。这里的 rC+c 即为每个点的通相。这里需要注意的是对于数学坐标系和这个矩阵的坐标系不要搞混。日常中的数学(x,y)坐标x代表横坐标,y代表纵坐标。而矩阵a[r][c]代表的是r行和c列,这x,y和r,c刚好是相反的,不要弄混了。对于之前使用比较多的是矩阵坐标系,推荐使用矩阵下的坐标系,因为查找元素更为方便。
同样一维索引也可以转换为二维坐标(c,r):( index% C, index / C)

找到顶点后,需要寻找边。
以(r,c)点为例,那么我们只需要遍历(r+1,c+0)(r-1,c+0)(r+0,c+1)(r+0,c-1)四个点,若某个点的值为1,则为这两个顶点之间存在一条边。
这里有个技巧:创建数组:dir[4][2]={{0,1},{0,-1},{1,0},{-1,0}}
给出伪码

int dir[4][2]={{0,1},{0,-1},{1,0},{-1,0}}
for(i 0:3)
	next_r = r +dir[i][0];
	next_c = c +dir[i][1];
	grid[r][c];

下面看代码逻辑(需要一定的转换技巧)

map<int,vector<int> > mp; //int->序号,vector<int>用来存储边
int dir[4][2]={{0,1},{0,-1},{1,0},{-1,0}};//四联通
int maxAreaOfIsland(vector<vector<int> >& grid) {
 	R = grid.size(); //行数
  	C = grid[0].size(); //列数
	int c;//行坐标
  	int r;//纵坐标
  	int nextr,nextc; 
  	vector<int> e; //用来存储边 
  	for(int i = 0; i < C*R; i++){
  		//i从0~R*C-1,i即一维索引,只需在矩阵中挑出grid[c][r]为1的顶点
   		c = i % C;//计算该点的列号
   		r = i / C;//计算列号

   		if(grid[r][c] == 1){//找到顶点
   			for(int j = 0; j < 4; j++){//通过四联通寻找边
   			//循环四次,寻找四个方位的点
     				nextr = r+dir[j][0];
     				nextc = c+dir[j][1];
          			if(is(nextr,nextc) && grid[nextr][nextc] == 1){
          			//判断该点的四个方位是否有顶点,若存在点,
          			//则该顶点到那个方位存在一条边
      					e.push_back(mta(nextr,nextc));//存储边 
     				}
    		}
    				//将所有的边都存储到mp中,并清空e,为下次存储边做准备
    				mp[mta(r,c)] = e;
    				e.clear();
   		}
  	} 

数据为:[[1,1,0,1,1],[1,0,0,0,0],[0,0,0,0,1],[1,1,0,1,1]]
在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在OpenGL窗口中同时显示三维模型二维模型,可以使用OpenGL的正交投影和纹理映射技术。具体步骤如下: 1. 创建OpenGL窗口并设置视口大小和投影矩阵 使用glViewport函数设置视口大小,使用glOrtho函数设置正交投影矩阵,这样可以将三维场景转换为二维。例如: ``` glViewport(0, 0, width, height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0.0f, width, 0.0f, height, -1.0f, 1.0f); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); ``` 2. 加载并渲染三维模型 使用OpenGL的模型加载库(如Assimp)加载三维模型,并使用OpenGL的绘制函数(如glDrawArrays或glDrawElements)渲染模型。例如: ``` // 加载模型数据 Assimp::Importer importer; const aiScene *scene = importer.ReadFile("model.obj", aiProcess_Triangulate | aiProcess_GenSmoothNormals | aiProcess_FlipUVs); // 渲染模型 for (int i = 0; i < scene->mNumMeshes; i++) { const aiMesh *mesh = scene->mMeshes[i]; // 绑定顶点缓冲区和索引缓冲区 glBindBuffer(GL_ARRAY_BUFFER, mesh->mVertexBuffer); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh->mIndexBuffer); // 设置顶点属性指针 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, position)); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, normal)); glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, texcoord)); // 绘制三角形 glDrawElements(GL_TRIANGLES, mesh->mNumFaces * 3, GL_UNSIGNED_INT, 0); } ``` 3. 加载并渲染二维模型 使用OpenGL的纹理映射技术加载二维模型,并使用OpenGL的绘制函数(如glDrawArrays或glDrawElements)渲染模型。例如: ``` // 加载纹理数据 GLuint texID; glGenTextures(1, &texID); glBindTexture(GL_TEXTURE_2D, texID); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // 渲染矩形 glBindTexture(GL_TEXTURE_2D, texID); glBegin(GL_QUADS); glTexCoord2f(0.0f, 1.0f); glVertex2f(0.0f, 0.0f); glTexCoord2f(0.0f, 0.0f); glVertex2f(0.0f, height); glTexCoord2f(1.0f, 0.0f); glVertex2f(width, height); glTexCoord2f(1.0f, 1.0f); glVertex2f(width, 0.0f); glEnd(); ``` 4. 刷新窗口并处理输入事件 使用glutMainLoop函数进入主循环,处理窗口刷新和输入事件。例如: ``` glutDisplayFunc(display); glutKeyboardFunc(keyboard); glutMainLoop(); ``` 其中,display和keyboard是用户自定义的回调函数,用于处理窗口刷新和输入事件。例如: ``` void display() { // 渲染三维模型 render3DModel(); // 渲染二维模型 render2DModel(); // 刷新窗口 glutSwapBuffers(); } void keyboard(unsigned char key, int x, int y) { // 处理键盘事件 switch (key) { case 'q': exit(0); } } ``` 以上是将三维模型二维模型放到一个OpenGL窗口的基本步骤,具体实现方式可能因开发环境和需求而有所不同。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值