ACM集训日记-8月7日

来源:互联网 发布:gekka睡眠面膜 知乎 编辑:程序博客网 时间:2024/05/18 12:38

    今天终于把搜索的部分给终结了,今天对于搜索的收获是,复习了(其实是忘光了)深搜中的剪枝手法,我们知道,深搜花费时间少,但是占用内存大,可以运用剪枝来减少空间,避免无用的搜索,比如变量在有界域上变动,先设置界限(有界剪枝),再进行搜索,如果不进行剪枝,对时间和内存要求苛刻的题目就会失败。

    然后就是上学期最后学的图论部分了,这块,我学的不是很好,今天重新看了一遍课件,了解了有向图和无向图,然后下面这个是给图的每一个点赋权值的操作

int i,j;    for (i = 1; i <= n; i++)      for (j = 1; j <= n; j++)        g[i][j] = 0x7fffffff(赋一个超大值);  //初始化,对于不带权的图g[i][j]=0,表示没有边连通。这里用0x7fffffff代替无穷大。    cin >> e;    for (k = 1; k <= e; k++)    {         cin >> i >> j >> w;  //读入两个顶点序号及权值         g[i][j] = w; //对于不带权的图g[i][j]=1         g[j][i] = w; //无向图的对称性,如果是有向图则不要有这句    } 
    课件上说建立邻接矩阵时,有两个小技巧:
 初始化数组大可不必使用两重for循环。
 1)如果是int数组,采用memset(g, 0x7f, sizeof(g))可全部初始化为一个很大的数(略小于0x7fffffff),使用memset(g, 0, sizeof(g)),全部清为0,使用memset(g, 0xaf, sizeof(g)),全部初始化为一个很小的数。  
    2)如果是double数组,采用memset(g,127,sizeof(g));可全部初始化为一个很大的数1.38*10306,使用memset(g, 0, sizeof(g))全部清为0。

    图的遍历也是有深度优先和广度优先。然后用到图论的题目基本是求最短路径之类的,就有一些算法

1.弗洛伊德算法

    是最简单的最短路径算法,可以计算图中任意两点间的最短路径。Floyed的时间复杂度是O (N3),适用于出现负边权的情况。

算法描述:
初始化:点u、v如果有边相连,则dis[u][v]=w[u][v]。
  如果不相连则dis[u][v]=0x7fffffff
For (k = 1; k <= n; k++)
    For (i = 1; i <= n; i++)
For (j = 1; j <= n; j++)
    If (dis[i][j] >dis[i][k] + dis[k][j])
        dis[i][j] = dis[i][k] + dis[k][j];
 算法结束:dis[i][j]得出的就是从i到j的最短路径。 

2.Dijkstra算法

    用来计算从一个点到其他所有点的最短路径的算法,是一种单源最短路径算法。也就是说,只能计算起点只有一个的情况。Dijkstra的时间复杂度是O (N2),它不能处理存在负边权的情况。

算法描述:
       设起点为s,dis[v]表示从s到v的最短路径,pre[v]为v的前驱节点,用来输出路径。
       a)初始化:dis[v]=∞(v≠s); dis[s]=0; pre[s]=0; 
       b)For (i = 1; i <= n ; i++)
            1.在没有被访问过的点中找一个顶点u使得dis[u]是最小的。
            2.u标记为已确定最短路径
            3.For 与u相连的每个未确定最短路径的顶点v
              if  (dis[u]+w[u][v] < dis[v]) 
               {
                  dis[v] = dis[u] + w[u][v];
                  pre[v] = u;
               }
        c)算法结束:dis[v]为s到v的最短距离;pre[v]为v的前驱节点,用来输出路径。

    今天主要还是看为主,先复习懂了才能做题。加油!

原创粉丝点击