DFS

                                         DAY 1

 

 

 

最短路能解决:边权固定

如果边权和经过点有关,相当于是有后效性,那么就需要dfs

组合:选择A,B,有一个附加代价C,这种情况只能搜索

缺点就在于枚举每一种可能性,时间复杂度贼大

1.状态表示

2.剪枝

最优答案(如果某个答案已经比最优答案差了就放弃)

记忆化剪枝(记搜)(还记得数位DP嘛)

可行性剪枝(字面意思,当前不可行了以后一定也不可行)

                                    DAY 1

 

可以看出:

1、n很小

2、图上没有重边,因此边数????≤28

3、边与边之间相互独立,因此不需要考虑边与边之间的相互影响

4、如果图上出现一棵树,则已满足连通图的要求

5、根据提示及第3条,一张图连通的概率为:该图中所有边都不被淹没的概率相乘

 

 

根据第1条:搜索,考虑每条边是否加入连通块

根据第4条:只要连通图中出现了一棵树,其余边是否被淹没不对答案产生影响

根据第2条:总状态数为2^28=268435456,看起来可能会被卡

根据第1、4条:搜索中最多选择????−1条边,因此总状态数小于????_28^7="1184040"。

根据第3、5条:可以计算出一张图出现的概率

 

需要什么:

1、搜索

2、并查集判断连通性

 

简单的剪枝:

    如果剩余的边数不够形成一棵树,则直接返回

                                        DAY 1

 

 

 

 

                                           DAY 1

 

建反图

原来不能同时存在的x和y有边,建反图之后就没边了

然后找最大团

先找一个点,往外扩展

对于一个点来说,只有和它有直接边的点才有可能与它构成团

就是一个剪枝,每一次经过一个点就把不可能的点都去掉

在一个点之后可能加入的序列中(默认序列点从小到大)

如果当前点的权值加上序列里所有点的权值都小于当前的答案,就剪枝

从i+1->i,最大答案就是i往前加上i+1

1.删点—序列

原来序列是123456

先dfs1,和它有边的点是356,tot=v[1]

然后找3,和它有边的点是6,tot=v[1]+v[3]

最后是6,没有和它有边的点tot=v[1]+v[3]+v[6]

然后把1删掉,序列变成23456

2.可行点—sum+tot<=ans

3.当前答案—ans[i]+tot<=ans

假如我们当前到了第i个点,这个点之前的点的ans都已经知道

我们枚举j是上一个点,如果ans[j]+tot<ans,那么j之前的点也不可行(因为ans一定<=j)

ans[i]表示从这个点开始搜的最大的权值和

tot表示当前搜到的最大团的权值和

Ans表示目前的最大的答案

Sum表示序列中剩下的点的权值和

那么为了能够当前答案剪枝,我们就需要把从1到n的序列倒过来dfs,即先算ans[n]

                                       DAY 1

 

 

                                       DAY 1

 

 

                                        DAY 1

 

                                          DAY 1

 

 

                                         DAY 1

 

 

                                       DAY 1

 

 

                                       DAY 1

 

 

                                      DAY 1

 

 

                                     DAY 1

 

 

                                     DAY 1

枚举每个位置的数,判断是否可以放

       当前行未出现过

       当前列未出现过

       当前格子未出现过

 

更新进入下一层

 

判断是否出现可以使用二进制

 

TLE?

 

倒序枚举即可

                                               DAY 1

 

 

 

                                                DAY 1

 

 

                                               DAY 1

 

 

                                              DAY 1

 

 

                                              DAY 1

 

 

                                              DAY 1

 

 

 


 

BFS

优先扩展浅层节点状态逐渐深入

通常用队列实现

最重要的是判重,即合理的表示状态

       新扩展出的节点如果和以前扩展出的节点相同,则这个新节点就不必再考虑

如何平衡时间和空间

       状态(节点)数目巨大,如何存储?

       怎样才能较快判断一个状态是否重复?

                                              DAY 1

 

 

 

                                             DAY 1

先排序(离散化)

Dis[x][y][t]表示在x,y,上一个线索是t的最小步数

 

 

 

queue<pair<int,int> > Q;
int FindPath(pair<int,int> b,pair<int,int> e) {
    for (int i=0;i<n;++i) for (int j=0;j<m;++j) dis[i][j]=1e9+10;
    Q.push(b); dis[b.first][b.second]=0;
    while (!Q.empty()) {
        pair<int,int> u=Q.front(); Q.pop();
        int x=u.first,y=u.second;
        for (int i=0;i<4;++i) {
            int tx=x+dx[i],ty=y+dy[i];
            if (CoordValid(tx,ty) && mp[tx][ty]!=0 && dis[tx][ty]>dis[x][y]+1) {
                dis[tx][ty]=dis[x][y]+1;
                Q.push(make_pair(tx,ty));    
            }
        }
    }
    return dis[e.first][e.second];
}    

                                               DAY 1

 

 

 

记录当前素数的值

每次选择一个位置,将其该改为另一个数

检查新的数是否是素数

                                            DAY 1

 

 

                                            DAY 1

 

 

                                          DAY 1

 

 

 

相当于移动到一个空位置花费为1、有守卫的位置花费为2

直接求最短路?

点数:????∗????≤40000

边数:????∗????∗2≤80000

直接求最短路可能超时,如何优化?

注意到边权只有1或2

为何不能直接BFS?

可以直接BFS求最短路的图边权只能是1。

只有边权为1才能保证在所有前驱结点都被扩展以后再扩展当前点

如何通过改变这个图使边权为1?

拆点?将每个点拆成一个入点一个出点?

增加了长度为0的边,可能导致错误

不能改变原有为1的边,如何特殊处理长度为2的边?

在到达‘x’点时,强制让当前点路径加1,将‘x’改为‘@’,不扩展当前点,使当前点重新入队。

为何不会影响最终答案?

由于路径长度为1:

其他点在重新进行扩展到达当前点时,最短路长度≥当前最短路长度+1

因此其他点无法更新当前点答案,最终答案因此也不会改变

                                             DAY 1

 

 

                                            DAY 1

 

 

 

 

 

  

Bfs本质是贪心?

队列是有序性,队首一定是最小的元素,队列是单增的序列,如果破坏了队列就不能

                                           DAY 1

 

 

 

d+2-->d+1+1      移动和杀死守卫,杀死守卫相当于从队首移到队尾

                                            DAY 1

 

 

                                              DAY 1

 

 

假设农夫起始位于点3,牛位于5,N=3,K=5,最右边是6。

如何搜索到一条走到5的路径?

策略1)深度优先搜索:从起点出发,随机挑一个方向,能往前走就往前走(扩展),走不动了则回溯。不能走已经走过的点(要判重)。

       要想求最优(短)解,则要遍历所有走法。

策略2)广度优先搜索:给节点分层。起点是第0层。从起点最少需n步就能到达的点属于第n层。

第1层:2,4,6

第2层:1,5

第3层:0

扩展时,不能扩展出已经走过的节点(要判重)

可确保找到最优解,但是因扩展出来的节点较多,且多数节点都需要保存,因此需要的存储空间较大 

                                             DAY 1

 

 

 

相关文章: