DAY 1

搜索枚举


 

DFS

                                         

 

 

 

最短路能解决:边权固定优化

若是边权和通过点有关,至关因而有后效性,那么就须要dfsspa

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

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

1.状态表示blog

2.剪枝排序

最优答案(若是某个答案已经比最优答案差了就放弃)队列

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

可行性剪枝(字面意思,当前不可行了之后必定也不可行)扩展

                                    

 

能够看出:搜索

一、n很小

二、图上没有重边,所以边数𝑚≤28

三、边与边之间相互独立,所以不须要考虑边与边之间的相互影响

四、若是图上出现一棵树,则已知足连通图的要求

五、根据提示及第3条,一张图连通的几率为:该图中全部边都不被淹没的几率相乘

 

 

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

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

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

根据第一、4条:搜索中最多选择𝑛−1条边,所以总状态数小于𝐶_28^7="1184040"。

根据第三、5条:能够计算出一张图出现的几率

 

须要什么:

一、搜索

二、并查集判断连通性

 

简单的剪枝:

    若是剩余的边数不够造成一棵树,则直接返回

                                        

 

 

 

 

                                           

 

建反图

原来不能同时存在的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]

                                       

 

 

                                       

 

 

                                        

 

                                          

 

 

                                         

 

 

                                       

 

 

                                       

 

 

                                      

 

 

                                     

 

 

                                     

枚举每一个位置的数,判断是否能够放

       当前行未出现过

       当前列未出现过

       当前格子未出现过

 

更新进入下一层

 

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

 

TLE?

 

倒序枚举便可

                                               

 

 

 

                                                

 

 

                                               

 

 

                                              

 

 

                                              

 

 

                                              

 

 

 


 

BFS

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

一般用队列实现

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

       新扩展出的节点若是和之前扩展出的节点相同,则这个新节点就没必要再考虑

如何平衡时间和空间

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

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

                                             

 

 

 

                                            

先排序(离散化)

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];
}    

                                               

 

 

 

记录当前素数的值

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

检查新的数是不是素数

                                            

 

 

                                            

 

 

                                          

 

 

 

至关于移动到一个空位置花费为一、有守卫的位置花费为2

直接求最短路?

点数:𝑁∗𝑀≤40000

边数:𝑁∗𝑀∗2≤80000

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

注意到边权只有1或2

为什么不能直接BFS?

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

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

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

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

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

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

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

为什么不会影响最终答案?

因为路径长度为1:

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

所以其余点没法更新当前点答案,最终答案所以也不会改变

                                             

 

 

                                            

 

 

 

 

 

  

Bfs本质是贪心?

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

                                           

 

 

 

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

                                            

 

 

                                              

 

 

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

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

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

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

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

第1层:2,4,6

第2层:1,5

第3层:0

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

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

                                             

相关文章
相关标签/搜索