您的位置:首页 > 其它

ACM集训日记-8月7日

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

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

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的前驱节点,用来输出路径。

    今天主要还是看为主,先复习懂了才能做题。加油!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: