zoukankan      html  css  js  c++  java
  • DS博客作业06--图

    求投食~(点图即可) # 1.本周学习总结 ## 1.1思维导图 ![](https://img2018.cnblogs.com/blog/1475360/201906/1475360-20190602205621946-1747640727.png)

    1.2谈谈你对图结构的认识及学习体会

    图中的顶点关系比树的更加复杂,不再是单纯的层次关系,而是平等的,点与点都可能连通,所以存储就需要模拟一个平面,在图的关系比较稀疏是用邻接表(使用线性存储),反之使用邻接矩阵,二维数据即可表示出一个平面。图的问题,主要是遍历和路径,难点在于找到相应算法(或者多种算法结合),解决一些实际问题时一般都会对算法进行相应的改动。
    

    2.PTA实验作业

    2.1.题目1:7-7 旅游规划

    有了一张自驾旅游路线图,你会知道城市间的高速公路长度、以及该公路要收取的过路费。现在需要你写一个程序,帮助前来咨询的游客找一条出发地和目的地之间的最短路径。如果有若干条路径都是最短的,那么需要输出最便宜的一条路径。
    输入格式:
    输入说明:输入数据的第1行给出4个正整数N、M、S、D,其中N(2≤N≤500)是城市的个数,顺便假设城市的编号为0~(N−1);M是高速公路的条数;S是出发地的城市编号;D是目的地的城市编号。随后的M行中,每行给出一条高速公路的信息,分别是:城市1、城市2、高速公路长度、收费额,中间用空格分开,数字均为整数且不超过500。输入保证解的存在。
    输出格式:
    在一行里输出路径的长度和收费总额,数字间以空格分隔,输出结尾不能有多余空格。
    输入样例:
    4 5 0 3
    0 1 1 20
    1 3 2 30
    0 3 4 10
    0 2 2 20
    2 3 1 20
    输出样例:
    3 40

    2.1.1设计思路

    此题就是找最短路径,可以使用Dijkstra,使用一个包括距离和价钱的结构体建图,然后比较时优先考虑距离其次到价格。
    

    结构体:

    typedef struct
    {
    	int weight=INF;//距离
    	int cost=INF;//价格
    }VNode;
    

    伪代码:

    int main()
    {
    	cin >> N >> M >> S >> D;
    	输入城市数量,和高速路和出发点、目的地 
    	for (i = 0  to M) 
    	{
    		cin >> x >> y >> w >> c;
    		读入高速路信息
    		graph[x][y].weight = graph[y][x].weight = w;//距离 
    		graph[x][y].cost = graph[y][x].cost = c;//价格 
    	}
    	调用Dijkstra(S, D);
    	return 0;
    }
    

    Dijkstra(S, D);函数

    void Dijkstra(int v,int d)
    {
    	VNode dist[501];//记录最短路径 
    	int k;
    	int s[501] = { 0 };//S[i]=1表示顶点i在S中,S[i]=0表示顶点i在u中 
    	VNode mindis; 
    	for (i = 0 to N)//N个顶点 
    	{
    		dist[i].weight = graph[v][i].weight;//距离初始化 
    		dist[i].cost = graph[v][i].cost;//价格初始化 
    	}
    	s[v] = 1;
    	for (i = 0 to N - 1)
    	{
    		mindis.weight = INF  初始化为最大值 
    		for (j = 0 toj < N)
    		{
    			if (s[j] == 0 && dist[j].weight <= mindis.weight)如果j属于u中(没有被选)并且距离小于等于最小值 
    			{
    				if (dist[j].weight < mindis.weight)距离小于最小值
    				{
    					k = j;
    					mindis.weight = dist[j].weight;
    					mindis.cost = dist[j].cost;
    					把该顶点信息记录 
    				}
    				else if(dist[j].cost < mindis.cost)距离相等,比较价格 
    				{
    					k = j;
    					mindis.cost = dist[j].cost;
    					把该顶点信息记录
    				}
    			}
    		}
    		s[k] = 1;
    		for (j = 0 to N)
    		{
    			if(j点属于u(没有被选过))
    				if(如果k和j连通)
    					if (graph[k][j].weight + dist[k].weight < dist[j].weight)如果过k点到j点的新路径比原来短 
    					{
    						dist[j].weight = graph[k][j].weight + dist[k].weight;更新为短路径 
    						dist[j].cost = graph[k][j].cost + dist[k].cost;
    					}
    					else if(graph[k][j].weight + dist[k].weight == dist[j].weight)
    					{
    						if (graph[k][j].cost + dist[k].cost < dist[j].cost)如果过k点到j点的新路径比原来便宜 
    						{
    							dist[j].cost = graph[k][j].cost + dist[k].cost;更新为新价格 
    						}
    					}
    		}
    	}
    	输出最短路径和价格 
    }
    

    2.1.2代码截图



    2.2.3本题PTA提交列表说明


    Q:

    看错题目然后误以为是输出目的地和价格,然后以为是bug找半天.。。。(还能过一个是最骚的),仔细看题目发现是输出路径的长度和价格

    2.2.题目2:7-6 修建道路

    N个村庄,从1到N编号,现在请您兴建一些路使得任何两个村庄彼此连通。我们称村庄A和B是连通的,当且仅当在A和B之间存在一条路,或者存在一个存在C,使得A和C之间有一条路,并且C和B是连通的。
    已知在一些村庄之间已经有了一些路,您的工作是再兴建一些路,使得所有的村庄都是连通的,并且兴建的路的长度是最小的。
    输入格式:
    第一行是一个整数N(3<=N<=100),代表村庄的数目。后面的N行,第i行包含N个整数,这N个整数中的第j个整数是第i个村庄和第j个村庄之间的距离,距离值在[1,1000]之间。
    然后是一个整数Q(0<=Q<=N*(N+1)/2)。后面给出Q行,每行包含两个整数a和b(1<=a<b<=N),表示在村庄a和b之间已经兴建了路。
    输出格式:
    输出一行仅有一个整数,表示为使所有的村庄连通需要新建公路的长度的最小值。
    输入样例:
    3
    0 990 692
    990 0 179
    692 179 0
    1
    1 2
    输出样例:
    179

    2.2.1设计思路

    此题要求是修建公路使得任何两个村庄都有路到达并且是最短,对于题中提到村庄之间已经有公路,只需把此类村庄的距离当做0即可。然后通过prim生成最小生成树
    注意:为了简单起见此题邻接矩阵的0并非常规prim算法中代表已经加入U(标记为选过),而是代表距离为0,标记则由visite[i]完成。
    
    int main()
    { 
    	for (i=1 to N) 
    	{
    		for (j = 1 to N) 
    		{
    			读入村庄之间的距离到矩阵中 
    		}
    	}
    	for (i = 0  to  q)
    	{
    		读入已经修有路的村庄 
    		graph[a][b] = graph[b][a]=0设置距离为零 
    	}
       调用prim函数 
    	输出最小修路长度 
    	return 0;
    }
    

    prim函数

    int Prim(int v)
    {
    	for (i = 1 to N)N个村庄 
    	{
    		对lowcost和closest数组初始化 
    		lowcost[i] = graph[v][i]距离 
    		closest[i] = v路径 
    	}
    	visite[v] = 1标记已经加入U 
    	for (i = 1 to N)
    	{
    		for (j = 1 to N)
    		{
    			查找lowcost中未加入U(即visite[j]=0)最小的点 
    			用k记录 
    		}
    		找到后把距离累加到sum中 
    		把该点标记已经加入U 
    		for (int j = 1; j <= N; j++)
    		{
    			修改lowcost和closet
    			if (visite[j]== 0 && graph[k][j] < lowcost[j])如果通过k到未选的点有短的距离 
    			{
    				lowcost[j] = graph[k][j];
    				closest[j] = k;
    			}
    		}
    	}
    	返回return sum;
    }
    

    2.2.2代码截图



    2.2.3本题PTA提交列表说明


    A:两个wa,是此处之前没有两个置为0(无向图),

    2.3.题目3:7-3 六度空间

    六度空间”理论又称作“六度分隔(Six Degrees of Separation)”理论。这个理论可以通俗地阐述为:“你和任何一个陌生人之间所间隔的人不会超过六个,也就是说,最多通过五个人你就能够认识任何一个陌生人。”如图1所示。

    假如给你一个社交网络图,请你对每个节点计算符合“六度空间”理论的结点占结点总数的百分比。
    输入格式:
    输入第1行给出两个正整数,分别表示社交网络图的结点数N(1<N≤10
    ​4
    ​​,表示人数)、边数M(≤33×N,表示社交关系数)。随后的M行对应M条边,每行给出一对正整数,分别是该条边直接连通的两个结点的编号(节点从1到N编号)。
    输出格式:
    对每个结点输出与该结点距离不超过6的结点数占结点总数的百分比,精确到小数点后2位。每个结节点输出一行,格式为“结点编号:(空格)百分比%”。
    输入样例:
    10 9
    1 2
    2 3
    3 4
    4 5
    5 6
    6 7
    7 8
    8 9
    9 10
    输出样例:
    1: 70.00%
    2: 80.00%
    3: 90.00%
    4: 100.00%
    5: 100.00%
    6: 100.00%
    7: 100.00%
    8: 90.00%
    9: 80.00%
    10: 70.00%

    2.3.1设计思路

    此题有点的像树的层次遍历,使用queue辅助搜索,visite[i]标记已经认识过的人,然后通过广度优先搜索,把所有人都认识完或者已经达到第六层(最多通过五个人认识)就可以结束搜索。
    
    图结构体
    typedef struct
    {
    	int **edgs;(直接声明数组会爆)
    	double n, e;
    }MatGraph;
    
    int main()
    {
    
    
        为邻接矩阵分配内存,直接声明会爆 
    	for (i =  0 to  M)邻接矩阵初始化 
    	{
    		int x, y;
    		cin >> x >> y;
    		G.edgs[x][y] = G.edgs[y][x] = 1;
    	}
    	for (i =  1  to  N)调用N次广搜 
    	{
    		调用BFS(G, i);
    	}
        delete内存 
    	return 0;
    }
    
    void BFS(MatGraph G,int v)
    {
    	使用cur表示当前访问的顶点 ,last表示该层次的最后一个顶点
    	当cur==last声明该层次遍历结束 
    	while (!q.empty()&&level<6)//队空或者层数到6 
    	{
    		从队列去队头元素 temp =cur= q.front();
    		for (int i = 1; i <=G.n; i++)
    		{
    			if (G.edgs[temp][i] != 0 && visite[i] == 0)寻找通过当前点可以认识其他点 
    			{
    				visite[i] = 1;标记已认识 
    				q.push(i);入队 
    				sum++;认识人数 
    			}
    		}
    		if (cur == last)//遍历一层结束 
    		{
    			if (!q.empty())
    			{
    				last = q.back();
    				level++;
    			}
    		}
    	}
    	printf("%d: %.2f%%
    ",v,sum*100 / (G.n));输出结果 
    }
    

    2.3.2代码截图

    2.3.3本题PTA提交列表说明


    A:直接过了,注意下层次和标记就可以了,

    3、上机考试错题及处理办法(-2--2分)

    3.1.截图错题代码

    3.1.1题目:六度空间

    3.2 错的原因及处理方法

    visite[i]等于1才是标记为已选,但是打错,然后编译器一直提示的是内存爆了,我以为是数组问题,后来才发现是该处错误引发的无限循环。
  • 相关阅读:
    网卡驱动引起openstack的mtu问题
    Ironic几种不同的场景下的网络拓扑
    enable multi-tenancy on openstack pike
    galera断电后无法重建集群
    Fabric单节点安装备忘
    OpenStack Ironic 常见问题
    Enable multi-tenancy on ironic
    kolla-ansible快速入门
    kolla管理openstack容器
    d2.js学习笔记(七)——动态SVG坐标空间
  • 原文地址:https://www.cnblogs.com/codedawn/p/10931560.html
Copyright © 2011-2022 走看看