m皇后(小白版)

2021-10-08 04:36:02 字數 3473 閱讀 8989

本題:

棋盤上有若干皇后,每個皇后有八個方向,分別是上、下、左、右、左上、右上、左下、右下。存在其他皇后在此皇后的這八個方向,那麼這個方向就是不安全的。

最後輸出在0,1,2,3,4,5,6,7,8個方向上不安全的皇后的個數。

看到這種皇后八個方向的問題,我們第一時間會想到的就是「八皇后問題」。從「八皇后問題」中,我們學到的一種方法:與主對角線(包含主對角線)平行的直線上點的橫縱座標之差為定值;與副對角線(包含副對角線)平行的直線上點的橫縱座標之和為定值。因此,對於本題也可以試試是否可以運用這個方法。

思考是否能暴力遍歷?

暴力1:遍歷每個點,暴力它的八個方向,有點就記錄,時間複雜度的極限大概是o(10^10),顯然不行。

暴力2:遍歷每個點,再確定其他點是否在它的八個方向上,有點就記錄,時間複雜度的極限大概也是o(10^10),顯然不行。

既然無法完全暴力,我們就要思考一下技巧了。

我們嘗試著從某個方向去遍歷所有的點

以確定某皇后左右是否安全為例:反映在圖上,就是找此皇后的左邊是否有皇后,右邊是否有皇后。可以發現,此時,若此皇后左右存在不安全的其他皇后,那麼這些皇后(包括此皇后)的橫座標都相同,不同的是縱座標。再深度思考一下,也就是說,我們實際上比較的是與此皇后橫座標相同的皇后的縱座標與此皇后的縱座標的大小關係(這句話有點繞 )。如果滿足「橫座標與此皇后相同」的條件,且「其縱座標小於此皇后的縱座標」,那麼就要標記此皇后的左側是乙個不安全的方向;如果滿足「橫座標與此皇后相同」的條件,且「其縱座標大於此皇后的縱座標」,那麼就要標記此皇后的右側是乙個不安全的方向。

進一步分析這個例子:如何高效的完成確定某皇后左右是否安全?這時我們要用到排序,按橫座標從小到大將所有皇后排序,橫座標相等的按縱座標從小到大排序,從橫座標相等的裡面比較縱座標就行了。這樣方便我們確定左右是否有其他皇后。(具體如何實現放在下乙個標題下了)

「確定某皇后左右是否安全」的例子探索完了,該解決其他方向上的了。模擬一下,要是「確定某皇后上下是否安全」,我們就找與此皇后縱座標相同的其他皇后,比較橫座標大小,進行記錄;要是「確定一三象限角平分線是否安全」,我們就找與此皇后橫縱座標之和相同的其他皇后,比較橫座標大小(比較縱座標也可以,本質就是找相對位置的關係),進行記錄;要是「確定二四象限角平分線是否安全」,我們就找與此皇后橫縱座標之差相同的其他皇后,比較橫座標大小(括號內容同上),進行記錄。

輸入:結構體輸入,包括x,y,id。其中x表示橫座標,y表示縱座標,id表示第id個皇后(就是為了給皇后編個號)

核心**實現:

建立四個cmp函式,用於分上述四種情況去sort。每次排完序之後,我們遍歷每個順序遍歷每個點。以確定某皇后左右是否安全為例,如果此點左邊的點的橫座標與此點的橫座標相同,那麼此點左邊的點的縱座標一定比此點小,因為咱們就是這麼排的序,所以滿足「此點左邊的點的橫座標與此點的橫座標相同」就讓cnt[此點id]++,cnt[此點左邊的點的id]++,表示此點左邊不安全,記錄一下;此點左邊的點的右邊不安全,記錄一下。以此迴圈。思考一下,其實被遍歷的每個點的cnt最多加兩次,一次是遍歷到自己時,另一次是遍歷到它後面的乙個點時。當遍歷到自己時,cnt[自己]++表示加上我左邊不安全的情況;當遍歷到自己的下乙個點的時候(即自己作為當前遍歷點的左邊的點時)cnt[自己,即當前遍歷點的左邊的點]++表示自己右邊不安全的情況。

其他三個情況類似,不再贅述。

輸出自己想辦法輸出cnt=0,1,2,3,4,5,6,7,8有幾個就行了,很簡單。

#include

using

namespace std;

const

int n=

100010

;int book[10]

,cnt[n]

;struct queenq[n]

;bool

cmp1

(queen a,queen b)

bool

cmp2

(queen a,queen b)

bool

c***

(queen a,queen b)

bool

cmp4

(queen a,queen b)

intmain()

//四個方向上判斷的**如出一轍

//判斷左右是否安全

sort

(q+1

,q+m+

1,cmp1)

;for

(int i=

2;i<=m;i++)if

(q[i]

.x==q[i-1]

.x)//判斷上下是否安全

sort

(q+1

,q+m+

1,cmp2)

;for

(int i=

2;i<=m;i++)if

(q[i]

.y==q[i-1]

.y)//判斷副對角線是否安全

sort

(q+1

,q+m+

1,c***)

;for

(int i=

2;i<=m;i++)if

(q[i]

.x+q[i]

.y==q[i-1]

.x+q[i-1]

.y)//判斷主對角線是否安全

sort

(q+1

,q+m+

1,cmp4)

;for

(int i=

2;i<=m;i++)if

(q[i]

.x-q[i]

.y==q[i-1]

.x-q[i-1]

.y)//輸出實現,book[i]記錄的是不安全方向數為i的皇后個數

for(

int i=

1;i<=m;i++

)for

(int i=

0;i<=

8;i++

) cout<<<

' ';

}

這部分一直是用來嗶嗶賴賴自己的,讀者忽略就行,完全為了警醒自己。

首先,我沒有ac,甚至可以說我不會,看了大佬的思路才寫了寫。用了lower & upper_bound,用錯了,也不知道咋改,最後放棄了。與大佬一樣的就是四個cmp函式。最後,好歹是臨摹出來了(堅決不能照抄**,和廢人沒什麼區別)

再者,得有四五天沒做題了,真的是慚愧,一直搞黑蘋果,可算搞完了,以後要邊複習課程邊學演算法,兩不誤。

總結一下本題中自己的問題所在:

1.主要問題在於自己的思維不夠靈活,想不到要如何暴力,如何遍歷。

2.**的實現,這個比較前乙個點與當前的點,這種遍歷方式並沒有想到,也就是沒抓到這樣暴力的本質:就倆方向,左/右,上/下……,說實話,這樣遍歷也挺巧妙的,不是我這種小白能達到的水平。要是雙重迴圈的話時間複雜度必然不行。

最後的最後我想問上天一句:我什麼時候才能成為大佬啊啊啊!!!

slam整體框架詳解(小白版)

本文是小白我學習slam的記錄,方便自己以後看起來沒有辣麼凌亂,當記個工程日誌嘛。典型的slam系統硬體組成主要由測距感測器,odometry 里程計,處理器,imu,運動機械人等。最簡單的結構為可以移動的機械人平台並且至少包含乙個測距單元。其過程包括特徵提取,資料關聯,狀態估計,狀態更新以及特徵更...

CCF 最大的矩形 C 小白版

在橫軸上放了n個相鄰的矩形,每個矩形的寬度是1,而第i 1 i n 個矩形的高度是hi。這n個矩形構成了乙個直方圖。例如,下圖中六個矩形的高度就分別是3,1,6,5,2,3。請找出能放在給定直方圖裡面積最大的矩形,它的邊要與座標軸平行。對於上面給出的例子,最大矩形如下圖所示的陰影部分,面積是10。第...

Linux 命令 make命令,小白版通俗入門

在make經典教程這篇文章中,對make講的很詳細,但是不太適合小白。乙個程式語言,從乙個個.h和.c檔案變成包含0和1的可執行檔案需要這麼幾個環節 源程式 預處理 編譯和優化 生成目標檔案 鏈結 可執行檔案。在linux上面我們可以用gcc編譯器 gcc c生成目標檔案,在用gcc o將目標檔案鏈...