博客作业06--图

1.学习总结

1.1图的思维导图

1.2 图结构学习体会

  • 深度优先遍历与广度优先遍历算法应该说是图中最基本的两个算法,许多算法都带有深度遍历与广度遍历的影子,所以是必须掌握的。
  • 克鲁斯卡尔算法是比普里姆算法更为精确的算法,但对于规模较大的最小生成树问题,求解速度较慢,所以稀疏图用克鲁斯卡尔算法,而稠密图用普里姆算法求解。
  • 在最小生成树中从一个顶点到另一顶点的路径不一定是最短的,但在狄克斯特拉树中从根结点到每个叶子结点的路径都是最短的。
  • 只有有向无环图才可以进行拓扑排序,所以拓扑排序可以用来判断图中是否存在环。

2.PTA实验作业

2.1.1 题目1:图着色问题

2.1.2 设计思路

int main()
{
    CreateMGraph();//建图
   
    for i=0 to N
        flag=1;colornum=0;//颜色数量
        for j=0 to n
            输入颜色;颜色数组存储颜色
            int Flag=0;
            for k=0 to k<j
                if 颜色数组中存在与当前颜色相同的,则判断错误,即Flag=1
            if 颜色正确
                颜色数量加一
        if 颜色数量不为K,判断为错误,即flag=0
        if 颜色数量正确
            for j=0 to n
                for k=0 to n 
                    judge(j);//进入函数判断配色方案是否正确
                    if flag==0
                        break;//停止循环
        if flag==1 输出 Yes
        else 输出 No
}
void judge(int p)
{
    if p遍历过 或 此时flag为0,则不再进行任何操作
    else
        标记p遍历过
        for i=0 to n
            if p与i有关联,即edges[p][i]==1
                if p处颜色与i处颜色相同
                    flag=0 并且停止循环
                else if i未遍历过
                    i进入函数judge进行递归
}

2.1.3 代码截图

2.1.4 PTA提交列表说明

  • 1.结构体中无法定义过大的数组
  • 2.缺少判断颜色数量是否正确的操作
  • 3.忘记将visited数组重置为0
  • 4.还有错误存在,但目前未找出来

2.2.1 题目2:公路村村通

2.2.2 设计思路

/*由普里姆算法改造*/
int prime(int n)
{
        cost[1]=0;   //初始化
        for i=2 to n   
            cost[i]=road[1][i];
        for i=1 to n
            min初始为一个极大值
            for j=1 to n
                if 通往j的费用不为0 且 小于 min
                    min=cost[j];k=j;
            if k!= 0
                num=cost[k]+num;//记录最小费用
                cost[k]=0;   // 作为记录过的标志
                for j=1 to n
                    if j未访问过 且 k到j的费用小于当前j的费用
                        cost[j]=coad[k][j];
                else
                    输出 -1;flag=1;退出结束循环
        if flag==0
            输出最低成本
}

2.2.3 代码截图

2.2.4 PTA提交列表说明

第一次提交时只有第一个测试点对,调试的时候发现当k==0时即表示找不到最小路径,此时就可以停止循环退出,多考虑反而会导致结果错误,但是仍有一个测试点不对,最后的通过是在完成7-7 即旅游规划那道题后面,尝试着也在数组初始化的时候做修改,于是通过了。

2.3.1 题目3:旅游规划

2.3.2 设计思路

/*该道题主要运用狄克斯特拉算法*/
void Dijkstra(int n,int c1,int c2)
{
    for i=0 to n   //初始化
        cost[i]=fare[c1][i];
        dist[i]=city[c1][i];
    visited[c1]=1;dist[c1]=0;
    for i=0 to n      //找出距离c1最小的点
        mindis初始化为最大数值
        for j=0 to n
            if j点未访问过 且 j到c1的距离小于mindis
                k=j;
                mindis=dist[j];//更新最小距离
        for j=0 to n      //修改未访问过顶点的距离
            if j未访问过
                    if k到j的距离加上此时最小距离小于j到c1的距离,改变j的数值
                        dist[j]=dist[k]+city[k][j];
                        cost[j]=cost[k]+fare[k][j];
                    else if 距离相同 且 所用费用小于此时总费用
                        cost[j]=cost[k]+fare[k][j];
}

2.3.3 代码截图

2.3.4 PTA提交列表说明

之前提交的时候只有第一个测试点是对的,上课的时候听同学讲矩阵中对角线初始为0,其余设为最大值,考虑到本题要求不大于500,INF就设为501,但是提交后发现当N,M为最大值时段错误,将初始数组的范围由M改成501,就对了。

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

本次题目集总分:310分

3.1 PTA排名

3.2 我的总分:206

4. 阅读代码

利用图完成数独

#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define ULL unsigned long long
typedef pair<int,int>pii;

const int N = 20;
const int mod = 765431;

int n=9;
char mp[N][N];  //  原图
char opt[N][N]; // 中间图
bool vol[N][N],row[N][N]; //row[i][j] 第i行中已经有j数字,vol[i][j]第i列中已经有j数字
pii P[100];int sz; // 存储所有的未知位置
int flag;

bool check(int now,int val){  // 查询 3*3宫
    pii p = P[now];
    int n=(p.first-1)/3*3;
    int m=(p.second-1)/3*3;

    for(int i=n+1;i<=n+3;i++){
        for(int j=m+1;j<=m+3;j++){
            if(opt[i][j] == val+'0') return false;
        }
    }
    return true;
}

void dfs(int now){
    if(flag) return ;
    if(now==sz) {
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++) {
                if(j!=1) putchar(' ');
                printf("%c",opt[i][j]);
            }
            puts("") ;
        }
        flag=1;
        return ;
    }

    pii p = P[now];
    for(int j=1;j<=9;j++){
        if( !row[p.first][j] && !vol[p.second][j] && check(now,j)){
            row[p.first][j]=1; vol[p.second][j]=1;
            opt[p.first][p.second]=j+'0';
            dfs(now+1);
            row[p.first][j]=0; vol[p.second][j]=0;
            opt[p.first][p.second]=mp[p.first][p.second];
        }
    }
}

int main(){
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            scanf("%c",&mp[i][j]);
            opt[i][j]=mp[i][j];
            if(mp[i][j] == '*') {
                P[sz].first=i;
                P[sz++].second=j;
            }else {
                int val=mp[i][j]-'0';
                vol[j][val]=1;
                row[i][val]=1;
            }
        }
        getchar();
    }
    flag=0;
    dfs(0);
    return 0 ;
}

前不久在玩数独,碰巧看到了用图来解决数独问题,觉得很有意思。

数独游戏要求九宫格中每一行每一列不能有重复的数字出现,那么就意味着这个程序需要不断进行比较判断,不能出现重复的数字。首先利用深度遍历往宫格里填数字,然后检查在该数字所处的行列是否有出现过,再在3*3的宫格里判断是否有相同的数字,若最后结果都不行则需要改变宫格中的数字,再次判断。

测试结果:

博客指路→(https://blog.csdn.net/qq_37383726/article/details/79703157)

posted @ 2018-06-17 21:27  看尽长安花  阅读(270)  评论(0编辑  收藏  举报