博客作业06--图

1.学习总结(2分)

1.1图的思维导图

1.2 图结构学习体会

谈谈你对图结构中的几个经典算法学习体会。具体有:

1.深度遍历算法
深度遍历理解起来还是比较好理解的,但是翻译成代码,却有点困难,基本上是照搬课本上的代码,其实最重要的是理解递归的思想,然后就是些代码的基本套路了,多读基本就能理解了。

2.广度遍历算法
广度遍历与深度遍历基本上是同一个模板的东西,只是不同于递归而是用了队列,跟树的遍历基本差不多,学习来比深度简单,但是代码要更多。

3.Prim和Kruscal算法
这两种算法都是生成最小二叉树的方法,这两种方法的基本思想能理解,就是从待选的边中找最小的边加入,但是代码实现的话,只用过prim算法,跟着课本些的,想了很久才理解了代码的实现,而且不知道课本上的代码有什么问题,pta的一道题中有一个点始终过不了,后来网上找了另一中prim算法,才过了,而Kruscal算法则没有用代码实现过,还是有点生疏。

4.Dijkstra算法
写这个算法的时候,发现其实根prim算法有点相似,都是初始化,找最小,更新,这种思路往下写的,不过特别的一点是,可以找到整条路径,但是思路也都差不多。

5.拓扑排序算法
这个算法就相对前面的算法相对简单,思路好理解,代码实现的话,有了前面的基础,写起来也是相对较简单的。

2.PTA实验作业(4分)

题目1:7-1 图着色问题

设计思路(伪代码或流程图)

主函数:
定义一个int类型的set s
输入图节点数,边数和颜色数
用creatMGraph建一个图
输入待检测的涂色方案数v
for i=0 to v
    输入涂色方案
    清空set
    通过放到set的颜色数比较是否正确
    if(set中的颜色数正确)
        通过Judge函数判断涂色方案是否正确
        if(返回1)输出yes
        else 输出no
    else
        输出no
end


Judge函数:
for i=0 to n
    for j=0 to n
        if(矩阵中存有边)
            if(边两个端点的颜色一样)
                返回0
    end
end
返回1


代码截图(注意,截图、截图、截图。代码不要粘贴博客上。不用用···语法去渲染)

PTA提交列表说明。

刚开始打算用邻接表做,写了好久,刚开始是MAXV的值设置的太小,导致运行错误,后来没有考虑到联通图与非联通图的判断,后来慢慢改只能如果就差一个卡DFS不重复访问顶点的错误实在是不懂什么意思,问了同学,他说使用邻接矩阵做的,没遇到这个错误,而且更简单,于是我干脆直接全改成了矩阵,花了一会而就都过了。

题目2:7-3 六度空间

设计思路(伪代码或流程图)

主函数:
输入节点数,边数建一个图
遍历每一个节点
    用BFS函数计算每个节点距离不超过6的结点数
    节点数出总数,输出

BFS函数:
定义数组visited存节点是否遍历
定义队列q
定义last存每层的最后一个节点
last初始等于待计算的节点v
初始visited数组
visited【v】=1,表示v已访问过
v入队
while(队列不空)
    取出队首元素
    for i=1 to n
        if(该元素未访问且跟i有边)
            入队
            visited数组中该元素标记为已访问
            cnt++
            定义tail记录最后存入队列的元素
    end
    if(v==last)
        level++
        更新last等于last
    if(level等于6)结束循环
end
返回cnt

代码截图(注意,截图、截图、截图。代码不要粘贴博客上。不用用···语法去渲染)

PTA提交列表说明。

这道题理解了思路后就会发现还是挺好做的,但是不清楚MAX的值才会提交了好多次。

题目3:7-6 修建道路

设计思路(伪代码或流程图)

主函数:
输入n建立矩阵
通过矩阵建图
输入v
for i=0 to v
    输入两个端点
    在邻接矩阵中把原来的边数变成1
end
调用Prim函数返回最小的生成树边的值
输出生成树的减v


Prim:

定义lowcost数组和closest数组
初始化这两个数组
for j=2 to n
    找最小的边数
    存下最小边数和节点
end
cnt+=min,way++
更新lowcost数组和closest数组
返回cnt

代码截图(注意,截图、截图、截图。代码不要粘贴博客上。不用用···语法去渲染)

PTA提交列表说明。

刚开始完全找不到思路怎么写,后来写了一个版本出来,结果只对了一个点,后来就完全找不到错误要怎么改,当时思路太乱,根本不知道怎么改。后来在舍友哪里听到了这个题目的类似取巧的方法,具体就是将已经修建的道路权值改写为1,所以在计算时权值为1的路就会作为最小的路径计算进去,只要到最后减掉修建的路数就可以,结果写了一下就对了。

3.截图本周题目集的PTA最后排名(3分)

3.1 PTA排名(截图带自己名字的排名)

3.2 我的总分:310

4. 阅读代码(必做,1分)

图的最短路径问题-Floyd算法-07-图4 哈利·波特的考试
哈利·波特要考试了,他需要你的帮助。这门课学的是用魔咒将一种动物变成另一种动物的本事。例如将猫变成老鼠的魔咒是haha,将老鼠变成鱼的魔咒是hehe等等。反方向变化的魔咒就是简单地将原来的魔咒倒过来念,例如ahah可以将老鼠变成猫。另外,如果想把猫变成鱼,可以通过念一个直接魔咒lalala,也可以将猫变老鼠、老鼠变鱼的魔咒连起来念:hahahehe。

现在哈利·波特的手里有一本教材,里面列出了所有的变形魔咒和能变的动物。老师允许他自己带一只动物去考场,要考察他把这只动物变成任意一只指定动物的本事。于是他来问你:带什么动物去可以让最难变的那种动物(即该动物变为哈利·波特自己带去的动物所需要的魔咒最长)需要的魔咒最短?例如:如果只有猫、鼠、鱼,则显然哈利·波特应该带鼠去,因为鼠变成另外两种动物都只需要念4个字符;而如果带猫去,则至少需要念6个字符才能把猫变成鱼;同理,带鱼去也不是最好的选择。

输入格式:

输入说明:输入第1行给出两个正整数N (≤100)和M,其中N是考试涉及的动物总数,M是用于直接变形的魔咒条数。为简单起见,我们将动物按1~N编号。随后M行,每行给出了3个正整数,分别是两种动物的编号、以及它们之间变形需要的魔咒的长度(≤100),数字之间用空格分隔。

输出格式:

输出哈利·波特应该带去考场的动物的编号、以及最长的变形魔咒的长度,中间以空格分隔。如果只带1只动物是不可能完成所有变形要求的,则输出0。如果有若干只动物都可以备选,则输出编号最小的那只。

输入样例:
6 11
3 4 70
1 2 1
5 4 50
2 6 50
5 6 60
1 3 70
4 6 60
3 6 80
5 1 100
2 4 60
5 2 80

输出样例:
4 70

#include<iostream>
using namespace std;

#define INFINITY 123456
#define MAXN 101

int Graph[MAXN][MAXN];
int dist[MAXN][MAXN];
int N,M;

//Floyd算法求最短路径 
void Flody() 
{
    int k,i,j;
    for(k=1; k<=N; k++){
        for(i=1; i<=N; i++){
            for(j=1; j<=N; j++){
                if(dist[i][k] + dist[k][j] < dist[i][j]){
                    dist[i][j] = dist[i][k] + dist[k][j];
                }
            }
        }
    }
}
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("hali.txt","r",stdin);
    #endif

    int i, j, x, y, weight;

    scanf("%d%d", &N, &M);

    //初始化图数组
    for(i=1; i<=N; i++){
        for(j=1; j<=N; j++){
            if(i == j)  Graph[i][j] = 0;
            else        Graph[i][j] = INFINITY;
        }

    }
    //读取数据 
    for(i=1; i<=M; i++){
        scanf("%d%d%d", &x, &y, &weight);
        Graph[x][y] = weight;
        Graph[y][x] = weight;
    }

    //初始化距离数组
    for(i=1; i<=N; i++){
        for(j=1; j<=N; j++){
            dist[i][j] = Graph[i][j];
        }

    }

    Flody();

    int minAnimal = -1, minDist = INFINITY;
    for(i=1; i<=N; i++){
        int tmp = 0;
        for(j=1; j<=N; j++){
            if(dist[i][j] > tmp)    tmp = dist[i][j];
        }

        if(tmp == INFINITY){
            printf("0\n");
            return 0;
        }
        //printf("%d\n",i);
        if(tmp < minDist){
            minAnimal = i;
            minDist = tmp;
        }
    }
    printf("%d %d\n", minAnimal, minDist);
    return 0;
} 

题目看起来特别的复杂,但是如果把动物看成图的顶点,魔咒的长度看成是顶点之间的权重的话,那么题目就变成了。求最短路径问题了。
这题用的是弗洛伊德算法来计算最短路径的问题,主干函数也就只有几行的代码,简单明了,值得借鉴。

posted on 2018-06-17 22:28  斯慕  阅读(277)  评论(2编辑  收藏  举报