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

擴展時,不能擴展出已經走過的節點(要判重)

可確保找到最優解,可是因擴展出來的節點較多,且多數節點都須要保存,所以須要的存儲空間較大 

                                             

相關文章
相關標籤/搜索