第1章 遊戲之樂 光影切割問題

2022-07-04 14:12:11 字數 2922 閱讀 3894

不少人很愛玩遊戲,例如 cs 。 遊戲設計也成為程式開發的熱點之一,我們假設要設計破舊倉庫之類的場景作為戰爭遊戲的背景。倉庫的地面會因為陽光從屋頂的漏洞或者視窗照射進來而形成許多光照區域和陰影區域。為了簡單起見,假設不同區域的邊界都是直線 , 我們把這些直線都叫做「光影線」,並且不存在三條光影線相交於一點的情況。 

那麼,如果我們需要快速計算某個時刻,在 x 座標[ a, b] 區間的地板上被光影劃分成多少塊。如何才能寫出演算法來計算呢? 

這個問題需要先自己歸納尋找規律。由於不存在三直線交於一點的情況,一些情況可以不用考慮。題目要求的是在a,b區間內,通過嘗試可以找到規律。如果只有一條線,那麼分割成兩塊空間。如果有兩條線,可能相交,也可能不相交(只要在a到b這個區間內不相交就行)。如果相交,那麼就分割成四塊,否則是三塊。

以此類推就會發現,分割塊數=線的數量+在這個區間內的交點數量+1,其中1為區間初始平面個數。

也就是說,只需要判斷在這個區間內的交點有幾個,經過這個區間的線有幾條即可。我們可以先進行一次預處理,計算出所有交點的位置,然後在每一次查詢時就可以很快查詢到了。

進一步分析圖1-12的右圖可以知道,區域內的交點數目就等於乙個邊界上交點順序相對另乙個邊界交點順序的逆序總數(這裡利用到條件「沒有三條直線相交於乙個點」)。在右圖中,左邊界順序為(a,b,c),右邊界為(c,b,a),假設a=1,b=2,c=3,那麼(c,b,a)=(3,2,1),它的逆序數為3。

因此,問題轉化為求乙個n個元素的陣列的逆序數。

最直接的求解逆序數方法還是o(n2),如果用分治的策略可以將時間複雜度降為o(n*log2n),求n個元素的逆序數的分治思想如下,首先求前n/2個元素的逆序數,再求後n/2個元素的逆序數,最後在排序過程中合併前後兩部分之間的逆序數。

package

chapter1youxizhilerevertsortcount;

/*** 光影切割問題

* 尋找逆序數的直接求法

* @author

dell *

*/public

class

revertsortcount1

/*** 直接尋找逆序數

* @return

*/public

intcount()}}

system.out.println();

return

cnt;

}public

static

void

main(string args) ;

revertsortcount1 rsc = new

revertsortcount1(a);

system.out.println("逆序數為:"+rsc.count());}}

程式執行結果如下:

逆序對為:(5, 4) (3, 2) (5, 2) (4, 2) (8, 2) (8, 6) 

逆序數為:6

package

chapter1youxizhilerevertsortcount;

/*** 光影切割問題

* 尋找逆序數的歸併演算法

* @author

dell *

*/public

class

revertsortcount2

/*** 歸併排序尋找逆序數

* 合併兩個有序陣列

* @param

a 待排序陣列

* @param

first 第乙個有序陣列在a中的起始位置

* @param

mid 第乙個陣列的最後乙個位置

* @param

last 第二個陣列的最後乙個位置

*/public

void merge(int a, int first, int mid, int

last)

else

b[k++]=a[j++];

count += mid-i+1; //

記錄逆序數

} }

while(i<=mid)

while(j<=last)

for(i=first;i<=last;i++)

}/*** 歸併排序

* @param

a 待排序陣列

* @param

first 陣列起始位置

* @param

last 陣列結束位置

*/public

void mergesort(int a, int first, int

last)

public

static

void

main(string args) ;

system.out.print("原陣列為:");

for(int i=0;i)

system.out.println();

revertsortcount2 rsc = new

revertsortcount2(a);

system.out.print("\n排好序的陣列為:");

for(int i=0;i)

system.out.println();

system.out.println("逆序數為:"+rsc.count);}}

程式執行結果如下:

原陣列為:3 5 4 8 2 6 9逆序對為:(5, 4) (3, 2) (4, 2) (5, 2) (8, 2) (8, 6) 

排好序的陣列為:2 3 4 5 6 8 9逆序數為:6

第1章 遊戲之樂 中國象棋將帥問題

中國象棋裡面雙方的 將 和 帥 各自呆在自己的九宮格裡,一步只能橫移或縱移一格,而且雙方不能見面 既不能處在同一條縱線上 在殘局時有的人會用這一規則走出絕妙殺招。假設一方的 將 為a,另一方的 帥 為b,現在求雙方所能出現的所有合法位置,所需變數只能用乙個位元組來儲存。我們用1 9的數字來,按行優先...

第1章 遊戲之樂 中國象棋將帥問題

中國象棋裡面雙方的 將 和 帥 各自呆在自己的九宮格裡,一步只能橫移或縱移一格,而且雙方不能見面 既不能處在同一條縱線上 在殘局時有的人會用這一規則走出絕妙殺招。假設一方的 將 為a,另一方的 帥 為b,現在求雙方所能出現的所有合法位置,所需變數只能用乙個位元組來儲存。我們用1 9的數字來,按行優先...

第1章 遊戲之樂 快速找出故障機器

題目 假設乙個機器只儲存乙個標號為id的記錄,假設每份資料儲存2個備份,這樣就有2個機器儲存了相同的資料。其中id是小於10億的整數 問題1 在某個時間,如果得到乙個資料檔案id的列表。是否能夠快速的找到這個表中僅出現一次的id?即快速找出出現故障的機器儲存的資料id。問題2 如果有兩台機器宕機呢?...