寫在前面:對於這個問題,首先我們可以採用暴力bfs或者dfs,但是這種演算法的複雜度是指數級的,如果考慮**30次,那麼它的迴圈次數是2在浩瀚的宇宙中,存在著1種生物, 這種生物可以發出宇宙射線!宇宙射線可以摧毀人的智商,進行降智打擊!302^
230,如果在正規比賽中肯定會超時,在詢問了大佬之後,這個問題可以採用dfs加上剪枝來解決,這裡和大家分享一下
宇宙射線會在無限的二維平面上傳播(可以看做乙個二維網格圖),初始方向預設向上。宇宙射線會在發射出一段距離後**,向該方向的左右45∘
45^45
∘方向**出兩條宇宙射線,同時威力不變!宇宙射線會**n
nn次,每次**後會在**方向前進a
aa個單位長度。
你的任務是計算出會有多少個位置被降智打擊。
input:輸入第一行包含乙個正整數n(n樣例輸入:≤30)n(n\leq 30)
n(n≤30
),表示宇宙射線會**nnn次
第二行包含n個整數a1,
a2..
.ana_,a_...a_
a1,a2
...
an,第i
ii個數ai(
ai≤5
)a_(a_\leq 5)
ai(ai
≤5)
表示第i
ii次**的宇宙射線會在它原方向上繼續走過多少個單位長度
output:
輸出乙個數ans
ansan
s,表示有多少個位置會被降智打擊
442
23
樣例輸出:
39
樣例解釋:
宇宙射線的**過程
首先我們通過觀察,宇宙射線的**其實是對稱的,我們只要求一半,另一半的座標就可以通過對稱得到。所以,在每一次**時,我們只考慮乙個方向,另乙個方向可以通過對稱得到。但是,不同的邊的對稱次數是不同的,例如,第一條邊,也就是圖中的出發邊,它不需要對稱,最後一條邊,也是圖中紫色的邊,它需要對稱3次。由此,我們可以得到,如果宇宙射線**n次,那麼最後一條邊需要對稱n-1次,倒數第二條邊需要對稱n-2次,由此類推,所以,我們就想到用dfs,首先遍歷到最後一條邊,然後從最後一條邊開始遍歷並回溯,回溯每一層最後一條邊都會對稱一次,其餘邊同理,這樣就能滿足我們的對稱需求。
在每一次**時,都會有兩個方向**,這裡我們只考慮乙個方向,朝右45∘
45^45
∘方向**,所以這裡我指定了兩個偏移量陣列,第0個方向是豎直向上**,然後按逆時針方向每變換45∘
45^45
∘度為乙個方向,那麼每一次**的方向計算為,假設原方向為dir
dirdi
r:(dir
+7)m
od8(dir+7)mod8
(dir+7
)mod
8,這樣我們就得到了每一次**的方向。每個射線都是沿**方向發散n個長度。
在考慮完方向問題,還有乙個對稱問題,對稱線一共有四條,如下圖:
幾幅圖旨在說明對稱關係,和實際的**圖的情況有些不類似,並且對稱點的計算方法高中都學過,這裡直接給出了對稱點的座標。
有了這幾個對稱關係,我們就能很容易的找到已經遍歷的對稱點。
對於演算法實現,上述都已經描述的差不多了。這裡我使用了stl中的set,因為他有乙個好處是自動去重,這樣我們就不用考慮乙個點是否已經到達過,直接將所有的點插入set中,set自動去除重複的點。這樣最後set中元素的個數就是我們的結果。
對於這個題目,我們最直接想到的就是暴力bfs和dfs,如果在沒有時間約束的條件下這樣也是可行的,如果一旦加上了時間約束,這往往就不盡人意了,所以我們要在此基礎上加上合理的剪枝,進一步減少冗餘的工作,減少時間。
#include
#include
#include
#include
#include
using
namespace std;
struct point};
set path;
//全域性變數,儲存已經到的點
int a[31]
;//八個方向,第0個方向為預設的向上方向
int x_move=
;int y_move=
;//startx和starty是**時的點
void
search
(int pnum,
int dir,
int startx,
int starty,
int n)
else
if(dir==
1||dir==5)
else
if(dir==
2||dir==6)
else
if(dir==
3||dir==7)
}//將已經到的邊對稱完,然後遍歷以startx和starty為終點的邊
for(
int i=
0;iintmain()
可怕的宇宙射線
題意 宇宙射線會在無限的二維平面上傳播 可以看做乙個二維網格圖 初始方向預設向上。宇宙射線會在發射出一段距離後 向該方向的左右45 方向 出兩條宇宙射線,同時威力不變。宇宙射線會 n次,每次 後會在 方向前進ai 個單位長度。計算出共有多少個位置會被打擊。輸入 輸入第一行包含乙個正整數n n 30 ...
CSP M1 C 可怕的宇宙射線 dfs剪枝
宇宙射線在二維平面內傳播,一段距離後向左右45 威力不變。宇宙射線會 n次,每次 後前進ai個單位再 計算共有多少二維平面內的點受到宇宙射線的攻擊。第一行 次數 n n 30 第二行 n個數,第i個數ai表示第i次 後前進的距離,ai 5 乙個數ans,表示共有ans個點被攻擊 每乙個點的狀態有橫座...
C 可怕的宇宙射線
宇宙射線會在無限的二維平面上傳播 可以看做乙個二維網格圖 初始方向預設向上。宇宙射線會在發射出一段距離後 向該方向的左右45 方向 出兩條宇宙射線,同時威力不變!宇宙射線會 n 次,每次 後會在 方向前進 ai個單位長度。求有多少個位置會被打擊。輸入第一行包含乙個正整數n n 30 表示宇宙射線會 ...