1 / 17

台北總公司/台北縣汐止市新台五路一段 112 號 10 樓 A 棟

書名 Java 於資料結構與演算法之實習應用 書號  PG20098 原著  河西朝雄 著 譯者 周明憲 / 徐堯譯. 台北總公司/台北縣汐止市新台五路一段 112 號 10 樓 A 棟 Building A, 10F, 112, Shin-Tai-Wu Road Sec. 1, Shijr, Taipei, Taiwan. 電話/ 02-26962869  傳真/ 02-26962867 台中辦事處/台中市文心路一段 540 號 4 樓 -1 4-1F, 540, Wen Shing Road, Sec. 1, Taichung, Taiwan.

lihua
Download Presentation

台北總公司/台北縣汐止市新台五路一段 112 號 10 樓 A 棟

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 書名 Java於資料結構與演算法之實習應用 書號 PG20098 原著 河西朝雄著 譯者 周明憲/徐堯譯 台北總公司/台北縣汐止市新台五路一段112號10樓A棟 Building A, 10F, 112, Shin-Tai-Wu Road Sec. 1, Shijr, Taipei, Taiwan. 電話/02-26962869 傳真/02-26962867 台中辦事處/台中市文心路一段540號4樓-1 4-1F, 540, Wen Shing Road, Sec. 1, Taichung, Taiwan. 電話/04-23287870 傳真/04-23108168 博碩網址:http://www.drmaster.com.tw

  2. 第九章 學習重點 • 電腦中最有發展的應用技術之一為遊戲。可以用雙手自由的操縱畫面中的虛構世界,這種快感正是電玩的魅力。這種遊戲若要創造出更精確的虛構世界,就必須具有在高度繪圖技術及即時(real-time)情況下能夠適時反應的速度,因此這是一種沒有電腦就無法玩的遊戲。 • 一般而言,遊戲(game)一詞令人有較為世俗的感覺,而益智(puzzle)則具有強烈的智慧思考遊戲的意義。古今中外,人們總會想出各種益智遊戲。這證明了不管是在哪個時代,人類對智慧的好奇心一樣都很旺盛。 • 若將電腦應用在益智遊戲上,便會有如第4章所示的河內塔問題一般,明快的獲得解決。但一般而言,益智遊戲無法適用明快的演算法,而益智遊戲所適用且演算法也常常須一五一十的檢查各項狀況。這種演算法有逆向追蹤與動態程式,本章會探討說明這兩個演算法。

  3. 9-1 魔術方塊 • 例題64 奇數魔術方塊將1~n2的數字排列在n×n(n為奇數)的正方形格子中,且各行、各列及各對角線的數字合計皆須相同 • 數字少的時候,試著數次將格子填滿,就能求出解答,但數字多的時候,這方法就不適用了。求出n×n(n=3、5、7、9、...)的魔術方塊的演算法之大致內容如下: (1)將1放入第1行的中央 (2)以方塊大小n除以放入數目的餘數若為1,則立即前進至下1個格子,否則前進至斜上方。 (3)若超出上方,則移至同1列的最下1格 (4)若超出右方,則移至同1行的最左1格

  4. public void paint(Graphics g) { final int N=7; // n魔術方塊(n=3,5,7,9,...) int i,j,k; int[][] hojin=new int[N+1][N+1]; j=(N+1)/2;i=0; for (k=1;k<=N*N;k++) { if ((k%N)==1) i++; else { i--;j++; } if (i==0) i=N; if (j>N) j=1; hojin[i][j]=k; } g.drawString("奇數魔術方塊(N="+N+")",140,20); for (i=1;i<=N;i++) { for (j=1;j<=N;j++) g.drawString(""+hojin[i][j],40*j,20*i+20); } }

  5. 練習問題64 4N魔術方塊 • 解4的倍數(4,8,12,16,...)的4N魔術方塊。 4×4方塊的解法如圖9.3所示。 (a) 由左上角開始從左到右的將1,2,3,4依序填入小格子內,再將5,6,7,8依序填入下一列的格子內,但不須將數字填入對角線內的格子。 (b) 由左上角開始從左到右的將16,15,14,13依序填入小格子內,再將12,11,10,9依序填入下一列的格子內,但只須將數字填入對角線的格子內。 (c) 將(a)與(b)組合起來即為解答。

  6. public void paint(Graphics g) { final int N=8; // 4N魔術方塊(n=4,8,12,16,...) int i,j; int[][] hojin=new int[N+1][N+1]; for (j=1;j<=N;j++) { for (i=1;i<=N;i++) { if (j%4==i%4 || (j%4+i%4)%4==1) hojin[i][j]=(N+1-i)*N-j+1; else hojin[i][j]=(i-1)*N+j; } } g.drawString("4N魔術方塊 (N="+N+")",160,20); for (i=1;i<=N;i++) { for (j=1;j<=N;j++) g.drawString(""+hojin[i][j],40*j,20*i+20); } }

  7. 9-2 戰略性猜拳 • 例題65 製作可讀出猜拳對手的習慣並使自己猜拳能力大增的程式 分別以0、1、2代表石頭、剪刀、布,然後製作如表9.1所示的電腦與人的猜拳對戰表。 當computer與man內分別存有0~2的資料時,則能以 (computer-man+3)%3 的值來進行下列的判定: 0 ... 平手 1 ...電腦輸 2 ...電腦贏 假設有人喜歡在出布以後再出石頭,也就是說這類人會受到自己先前出的拳的影響而決定出下一拳。電腦若遇到這種對手,則其戰略為: 設對手之前出的拳為M,目前出的拳為man時,則表9.2的戰略表的table[m][man]的內容便要+1。猜拳時若使用這個方法,則可至做出如圖9.2所示的戰略資料。 table[m][man]

  8. 宣告 class Rei65Frame extends Frame { private Checkbox cb1,cb2,cb3; private TextArea ta; private int[][] table={{0,0,0}, // 戰略表 {0,0,0}, {0,0,0}}; private int[] hist={0,0,0}; // 勝敗次數 private String[] hand={"石頭","剪刀","布"}; private String[] msg={"平手","你贏","電腦贏"}; private int m=0; ………………………………

  9. public void actionPerformed(ActionEvent e) { int computer,man,jg; if (cb1.getState()) man=0; else if (cb2.getState()) man=1; else man=2; if (table[m][0]>table[m][1] && table[m][0]>table[m][2]) computer=2; else if (table[m][1]>table[m][2]) computer=0; else computer=1; jg=(computer-man+3) % 3; hist[jg]++; table[m][man]++; // 學習 m=man; ta.setText("電腦出:"+hand[computer]+"\n"+ "判定:"+msg[jg]+"\n"+ "你的勝敗結果:"+hist[1]+"勝"+hist[2]+"敗"+hist[0]+"平手\n"); }

  10. 9-3 逆向追蹤 • 逆向追蹤(back tracking)並不是要徹徹底底的搜尋全部的局面,而是有效率的判定不須搜尋的局面、並降低搜尋時間的演算法。 • 練習問題66 8個皇后在8×8的棋盤上放置8個西洋棋的皇后棋子,然後求出所有皇后都互不對立的局面。西洋棋的皇后棋子可縱向、橫向與斜向前進。所謂的互不對立是指,某一皇后棋子可以前進的位置其他的皇后棋子不會進入。

  11. private int[] column=new int[N+1], // 表示同一欄內是否有皇后棋子 rup=new int[2*N+1], // 表示是否在由右上角至左下角的對角線上 lup=new int[2*N+1], // 表示是否在由右下角至左下角的對角線上 queen=new int[N+1]; // 皇后棋子的位置 private int num; // 解答的編號 private String result; // 顯示結果

  12. void backtrack(int i) { int j,x,y; if (i>N) { result=result+"\n解答"+(++num)+"\n"; for (y=1;y<=N;y++) { for (x=1;x<=N;x++) if (queen[y]==x) result=result+" Q"; else result=result+" ."; result=result+"\n"; } } else { for (j=1;j<=N;j++) { if (column[j]==1 && rup[i+j]==1 && lup[i-j+N]==1) { queen[i]=j; // (i,j)為皇后棋子的位置 column[j]=rup[i+j]=lup[i-j+N]=0; // 局面的變更 backtrack(i+1); column[j]=rup[i+j]=lup[i-j+N]=1; // 回復至原貌 } } } }

  13. 9-4 動態規劃 • 動態規劃(dynamic programming)是最化畫問題的有效解法。 • 求n個元素的最佳解時,可將由i個元素組成的部分集合最佳解製成表格後,求出結果。當增加1個元素時,便以此表為基礎計算出最佳解的變化,然後根據計算結果修改表格的內容。如此反覆操作直至全部集合(n個元素全部)均執行完畢,最後最佳解就可由表中求得。也就是說,動態規劃為從空集合的最佳解(初始值)開始,每當增加1個元素就將最佳解更新,而求得全部集合的最佳解之方法

  14. 背包問題與最佳解判定 將物品i放入時,大小s的背包的最佳解是否變更可由下列的式子來判定。 (1)將物品i放入至大小s的背包內後的剩餘空間設為p。 (2)將與 p同樣大小的背包之現在最佳解加上物品i的金額,並將此金額設為newvalue。 (3)若newvalue>「大小s的背包之現在最佳解(value[s])」,則 ‧以newvalue修改大小s的最佳解 ‧將物品i視為最後放入背包的物品,並記錄至item[s]。

  15. public void paint(Graphics g) { final int Limit=8, // 背包的重量限制 N=5, // 物品的種類 Min=1; // 重量的最小值 int i,s,p; int[] item=new int[Limit+1]; long[] value=new long[Limit+1]; long newvalue; class body { String name; // 品名 int size; // 重量 long price; // 價格 public body(String n,int s,long p){ name=n; size=s; price=p; } } body[] a={new body("plum",4,4500),new body("apple",5,5700), new body("orange",2,2250),new body("strawberry",1,1100), new body("melon",6,6700)}; ………………

  16. for (s=0;s<=Limit;s++) { value[s]=0; // 初始值 } for (i=0;i<N;i++) { // 物品的編號 for (s=a[i].size;s<=Limit;s++) { // 背包的大小 p=s-a[i].size; // 空背包的大小 newvalue=value[p]+a[i].price; if (newvalue>value[s]) { value[s]=newvalue;item[s]=i; // 最佳解的修改 } } } int y=1; g.drawString("品名",10,20); g.drawString("價格",80,20); for (s=Limit;s>=Min;s=s-a[item[s]].size) { g.drawString(""+a[item[s]].name,10,y*20+20); g.drawString(""+a[item[s]].price,80,y*20+20); y++; } g.drawString("合計",10,y*20+20); g.drawString(""+value[Limit],80,y*20+20); }

More Related