幾種典型的搜尋題型(一)

2021-08-07 06:00:17 字數 4044 閱讀 2417

搜尋題型很多.但身為菜鳥的我,僅僅只能挑出一些常見的簡單題型來講解一番了。

因為不懂什麼專業的術語,下面題型都是我自己命名,請不要見怪哦。

一、合併周邊同類問題基礎版——oil deposits

題意:

有一塊空地,『@』代表油田,』*』不是油田。然後若是兩個油田橫豎斜三個方向中有乙個方向是相連線的那麼把這兩個油田看做乙個油田。

輸入:

n, m和矩陣字串,以0 0結束 (1<=n,m<=100)

輸出 一共有幾個油田

**如下:

#include 

using namespace std;

const int maxn = 101;

char mat[maxn][maxn];

//next陣列用於存入八個方向

, ......}這樣看就清晰明了了。

intnext[8][2] = ;

intn, m;

//用深度搜尋探查油田

void

dfs(int

x, int

y);int

main()}}

cout

<

<

}return 0;

}void

dfs(int

x, inty)}

二、合併周邊同類問題公升級版——island問題gym - 101291h

題意:

海上航拍**有三種狀況,分別是島嶼』l』、海水』w』、還有被雲霧遮擋的未知地方』c』。未知地方可能是島,也可能是海水。把共有一邊的島嶼看作是乙個島。求最小島嶼的數量。

輸入:

n, m和矩陣字串(1<=n,m<=50)

輸出 一共有幾個島嶼。

如: input

3 2

lw cc

wl output

1這道題不定因素是』c』部分,不過大體**不改變,遇到島嶼開始深搜並且島嶼數量加一,在深搜中只要不是』w』就可以繼續進行深搜。**如下:

#include 

using

namespace

std;

const

int maxn = 101;

char mat[maxn][maxn];

int next[4][2] = ;

int n, m;

void dfs(int x, int y);

int main()}}

cout

void dfs(int x, int y)

}

三、合併周邊同類問題豪華版——coconuts

題意:

有一吃貨做夢,夢裡有一地方,滿格都是椰子,椰子有好有壞。吃貨一次性可以吃了所有想連線的好椰子,即橫豎方向上若是有好椰子相連線,都可以一次吃完。求吃貨需要花幾次吃完所有的椰子。

輸入 測試的案例數t

每個案例要求輸入行r、列c和壞椰子的數量n

(0 < r, c <= 1e9、0<= n <= 200)

輸出 吃了幾次,並且把每次吃的椰子數從小到大輸出。

看到行和列的範圍就頭疼了,這更本無法直接建立乙個二維陣列儲存資料。

於是乙個新的方法出來了——離散化(discretization)!!!

那麼什麼是離散化?在此不多講解,離散化詳解傳送位址——什麼是離散化?

可以看出,壞椰子的個數在200以內,數量少,故而,可以從壞椰子的座標入手,把壞椰子的所有座標的 x 和 y 分別進行離散化,然後還需要鏈結好每個離散化後的 x 和 y ,這樣就構造成了離散化後的座標。即需要構造兩個陣列x和y。

如何離散乙個某一方向上的點,拿x軸方向來說。

如果x[i] = x[i-1],那麼就就離散到x[i-1]同一行;

如果x[i] = x[i-1] + 1,那麼就離散到x[i-1]對應的下一行;

其他情況則離散到x[i-1]對應的下一行的下一行。

離散x軸的圖如下:

設每一段的長度為dx,但每段或虛或實。

實線段的長度dx = 1;

虛線段的長度dx = x[i] - x[i-1] - 1。即兩個點的距離,再減去乙個實線段dx的長度就是虛線dx的長度。

這就是離散化x軸方向座標操作,y軸也是同樣如此。

具體實現**如下:

#include 

using

namespace

std;

#define ll long long

const

int maxn = 405;

//定義結構體,v代表離散前的座標值,p代表離散後的座標值

//id是點座標的標記,方便離散後可以連線x與y,成功構造出乙個離散點

struct node

x[maxn], y[maxn];

//用於區分好壞椰子座標

bool mark[maxn][maxn];

//離散化後x軸y軸每條線段的長度

ll dx[maxn], dy[maxn];

int next[4][2] = ;

ll r, c;

int n;

//cmp1排序好離散前的座標值,cmp2是用來排序id以便連線出離散點

bool cmp1(node p1, node p2);

bool cmp2(node p1, node p2);

//離散化函式,引數s,放入x軸或y軸方向的座標陣列,引數ds放入線段長度素組,len為某方向上的範圍。

void disc(node* s, ll* ds, ll &len);

//合併周邊同類問題必寫的遞迴,稍微改變一番

ll dfs(int x, int y);

int main()

sort(x+1, x+n+1, cmp1);

sort(y+1, y+n+1, cmp1);

disc(x, dx, r);

disc(y, dy, c);

sort(x+1, x+n+1, cmp2);

sort(y+1, y+n+1, cmp2);

memset(mark, false, sizeof(mark));

//把壞椰子打上標記

for(int i=1; i<=n; i++)

mark[x[i].p][y[i].p] = true;

int cur = 0;

ll ans[maxn];

for(ll i=1; i<=r; i++)

for(ll j=1; j<=c; j++)

if(!mark[i][j]) ans[cur++] = dfs(i, j);

sort(ans, ans+cur);

printf("case #%d:\n", cas);

cout

<

cout

bool cmp1(node p1, node p2)

bool cmp2(node p1, node p2)

void disc(node* s, ll* ds, ll &len)

else

if(s[i].v == s[i-1].v + 1)

else

}//原來的範圍變為離散化後的範圍

len = cur;

}ll dfs(int x, int y)

return sum;

}

呼終於打完這段**了,特別長,敲得頭暈。不過收穫不小。

好了以上三題是我至今遇到的幾個典型的合併周邊同類問題。這一類的問題暫且先寫到此處,若是以後遇到其他典型的題,我會適當修整部落格。

這篇部落格已經很長了,姑且寫到這裡,餘下的題型將會抽空補齊。

排序的幾種題型

acwing 103.電影 應用 給定n個數,1,2,100000,1000000,3 n不大,但是數很大。此時可以先對這些數排序,放到乙個陣列裡,這樣就建立了這些數與0,1,2 n的對映。之後用1,2 n來代替這些數,可以建立更方便的對映。如果這些數中有重複,需要去重,順便把數量記錄下來。因為已經...

wget的幾種典型用法 介紹典型的

wget的幾種典型用法 介紹典型的 一.最簡單的用法 wget wget mirror convert links 或短寫引數 wget m k 五.其它有用的引數說明 tries number t number 指定連線失敗時重試次數,0或inf表示無限重試,預設值為20。但如果遇到 連線被拒絕 ...

NOJ 2074 pdf的旅遊 典型DFS題型

典型的dfs題目,注意結束條件的判斷。如下 include include using namespace std bool map 15 15 bool vis 15 int res 15 int n,m n表示有幾個地點,m表示有幾條路 bool dfs int s,int d s表示當前開始的...