算法筆記_201:第三屆藍橋杯軟件類決賽真題(Java本科)


 

目錄

數量周期

提取子串

源碼變換

古代賭局

火柴游戲

 

前言:以下代碼僅供參考,若有錯誤歡迎指正哦~


數量周期

 

【結果填空】(滿分9分)

    復雜現象背后的推動力,可能是極其簡單的原理。科學的目標之一就是發現紛繁復雜的自然現象背后的簡單法則。愛因斯坦的相對論是這方面的典范例證。

    很早的時候,生物學家觀察某區域某種昆蟲的數量(稱為蟲口數)之逐年變化規律,就十分迷惑:有的時候是逐漸增多達到一個平衡值。有的時候在兩個數字間周期跳動。有的時候則進入一片混亂,類似隨機數字一樣變化(稱為混沌現象)。

    慢慢地,人們從數學中更清晰地觀察到了這一現象,並因此開創了:符號動力學、非線性動力學等研究領域。

    一個著名的蟲口數目簡化模型如下:

    x' = x * (1 - x) * r

    這里,x  x' r 都是浮點數。
 
    其中,x 表示當年的蟲口數,x' 表示下一年的蟲口數。它們的取值范圍在 0 與 1 之間,實際上表示的是:蟲口的總數占環境所能支持的最大數量的比率。

    r 是常數(環境參數),r的取值范圍在 [0,4]。

    令人驚訝的是:這個簡單的迭代公式有着不同尋常的神秘性質!

    一般來說,多次迭代后,蟲口數的穩定模式與x的初始值無關,而與 r 有關!

    例如:無論x初始值是多少,當 r = 2.5 的時候,x 多次迭代后會趨向於 0.6。

    而當 r = 3.2 的時候,x 的值會趨向於在 0.799 與 0.513 之間周期性擺動。

    那么,r = 3.62 的時候,你觀察到有什么周期現象發生嗎?



    不需要提交源代碼,只要寫出你的結論即可!

    答案寫在:“解答.txt”中,不要寫在這里。


x值出現混沌現象  

 

 1 public class Main {
 2 
 3     public static void main(String[] args) {
 4         double r = 3.62;
 5         double x = 0.1;
 6         for(int i = 1;i < 2000;i++) {
 7             x = x * (1 - x) * r;
 8             System.out.println("x = "+x);
 9         }
10     }
11 }

 

 

 


提取子串

【代碼填空】(滿分12分)
    
    串“abcba”以字母“c”為中心左右對稱;串“abba” 是另一種模式的左右對稱。這兩種情況我們都稱這個串是鏡像串。特別地,只含有1個字母的串,可以看成是第一種模式的鏡像串。 

    一個串可以含有許多鏡像子串。我們的目標是求一個串的最大鏡像子串(最長的鏡像子串),如果有多個最大鏡像子串,對稱中心靠左的優先選中。例如:“abcdeefghhgfeiieje444k444lmn”的最大鏡像子串是:“efghhgfe”

    下面的靜態方法實現了該功能,請仔細閱讀並分析代碼,填寫空白處的代碼,使得程序的邏輯合理,結果正確。

// 求最大(長度最大)鏡像對稱子串
public static String getMaxMirrorString(String s)
{
    String max_s = "";  // 所求的最大對稱子串

    for(int i=0; i<s.length(); i++)
    {
        // 第一種對稱模式
        int step = 1;
        try{
            for(;;)
            {
                if(s.charAt(i-step) != s.charAt(i+step)) break;
                step++;
            }
        }catch(Exception e){}
        
        String s1 = s.substring(_____________________________);     // 填空1
        
        
        // 第二種對稱模式
        step = 0;
        try{
            for(;;)
            {
                if(_________________________________) break;    // 填空2
                step++;
            }
        }catch(Exception e){}
        
        String s2 = s.substring(i-step+1,i+step+1);
        
        
        if(s1.length() > max_s.length()) max_s = s1;
        if(s2.length() > max_s.length()) max_s = s2;
    }
    
    return max_s;                
}


【注意】
    只填寫缺少的部分,不要抄寫已有的代碼。
    所填寫代碼不超過1條語句(句中不會含有分號)
    所填代碼長度不超過256個字符。
    答案寫在“解答.txt”中,不要寫在這里!


i-step+1, i+step s.charAt(i-step) != s.charAt(i+step+1)

 

 

 


源碼變換

 

【編程題】(滿分22分)

    超文本標記語言(即HTML),是用於描述網頁文檔的一種標記語言。

    HTML通過文本來描述文檔顯示出來應該具有的“樣子”。它主要通過標簽來定義對象的顯示屬性或行為。

    如果把java的源文件直接拷貝到HTML文檔中,用瀏覽器直接打開,會發現本來整齊有序的源文件變成了一團遭。這是因為,文本中的許多回車和空格都被忽略了。而有些符號在html中有特殊的含義,引起了更復雜的局面。

    為了源文件能正常顯示,我們必須為文本加上適當的標簽。對特殊的符號進行轉義處理。

    常用的有:
    HTML 需要轉義的實體:
    &     --->  &amp;
    空格  --->  &nbsp;
    <     --->  &lt;
    >     --->  &gt;
    "     --->  &quot;
    此外,根據源碼的特點,可以把 TAB 轉為4個空格來顯示。
    TAB   --->  &nbsp;&nbsp;&nbsp;&nbsp;

    為了顯示為換行,需要在行尾加<br/>標簽。

    為了顯示美觀,對關鍵字加粗顯示,即在關鍵字左右加<b>標簽。比如:

    <b>public</b>

    對單行注釋文本用綠色顯示,可以使用<font>標簽,形如:

    <font color=green>//這是我的單行注釋!</font>

    注意:如果“//”出現在字符串中,則注意區分,不要錯誤地變為綠色。

    不考慮多行注釋的問題(/* .... *//** .... */)

    你的任務是:編寫程序,把給定的源文件轉化為相應的html表達。

【輸入、輸出格式要求】

    與你的程序同一目錄下,存有源文件 a.txt,其中存有標准的java源文件。要求編寫程序把它轉化為b.html。

    例如:目前的 a.txt 文件與 b.html 文件就是對應的。可以用記事本打開b.html查看轉換后的內容。用瀏覽器打開b.html則可以看到顯示的效果。

    注意:實際評測的時候使用的a.txt與示例是不同的。    

【注意】

    請仔細調試!您的程序只有能運行出正確結果的時候才有機會得分!
    
    請把所有類寫在同一個文件中,調試好后,存入與【考生文件夾】下對應題號的“解答.txt”中即可。
    
    相關的工程文件不要拷入。
    
    請不要使用package語句。
    
    源程序中只能出現JDK1.5中允許的語法或調用。不能使用1.6或更高版本。  
    
 1 import java.io.BufferedReader;
 2 import java.io.FileReader;
 3 import java.io.PrintWriter;
 4 
 5 public class Main {
 6     
 7     public static String process(String s) {
 8         StringBuilder t = new StringBuilder("");
 9         char[] A = s.toCharArray();
10         for(int i = 0;i < A.length;i++) {
11             if(A[i] == '&')
12                 t.append("&amp;");
13             else if(A[i] == ' ')
14                 t.append("&nbsp;");
15             else if(A[i] == '>')
16                 t.append("&gt;");
17             else if(A[i] == '<')
18                 t.append("&lt;");
19             else if(A[i] == '"')
20                 t.append("&quot;");
21             else if(A[i] == '\t')
22                 t.append("&nbsp;&nbsp;&nbsp;&nbsp;");
23             else
24                 t.append(A[i]);
25         }
26         String r = t.toString();
27         r = r.replaceAll("public", "<b>public</b>");
28         r = r.replaceAll("static", "<b>static</b>");
29         r = r.replaceAll("class", "<b>class</b>");
30         r = r.replaceAll("void", "<b>void</b>");
31         int n = r.lastIndexOf("//");
32         if(n != -1) {
33             String temp = r.substring(n);
34             r = r.replaceAll(temp, "<font color=green>"+temp+"</font>");
35         }
36         r = r + "<br/>\n";
37         return r;
38     }
39     
40     public static void main(String[] args) throws Exception {
41         BufferedReader read = new BufferedReader(new FileReader("a.txt"));
42         PrintWriter psw = new PrintWriter("b.html");
43         String s;
44         psw.write("<html><body>\n");
45         while((s = read.readLine()) != null) {
46             psw.write(process(s));
47         }
48         psw.write("</body></html>");
49         read.close();
50         psw.close();
51         //System.out.println("轉換成功!!!");
52     }
53 }

 

 

 


古代賭局

 

【編程題】(滿分23分)

    俗話說:十賭九輸。因為大多數賭局的背后都藏有陰謀。不過也不盡然,有些賭局背后藏有的是:“陽謀”。

    有一種賭局是這樣的:桌子上放六個匣子,編號是1至6。多位參與者(以下稱玩家)可以把任意數量的錢押在某個編號的匣子上。所有玩家都下注后,庄家同時擲出3個骰子(骰子上的數字都是1至6)。輸贏規則如下:

    1. 若某一個骰子上的數字與玩家所押注的匣子號相同,則玩家拿回自己的押注,庄家按他押注的數目賠付(即1比1的賠率)。

    2. 若有兩個骰子上的數字與玩家所押注的匣子號相同,則玩家拿回自己的押注,庄家按他押注的數目的2倍賠付(即1比2的賠率)。

    3. 若三個骰子上的數字都與玩家所押注的匣子號相同,則玩家拿回自己的押注,庄家按他押注的數目的6倍賠付(即1比6的賠率)。

    4. 若玩家所押注匣子號與某個骰子示數乘積等於另外兩個骰子示數的乘積,則玩家拿回自己的押注,庄家也不賠付(流局)。

    5. 若以上規則有同時滿足者,玩家可以選擇對自己最有利的規則。規則執行后,則庄家收獲所有匣子上剩余的押注。

    乍一看起來,好像規則對玩家有利,庄家吃虧。但經過大量實戰,會發現局面很難說,於是懷疑是否庄家做了手腳,庄家則十分爽快地說:可以由玩家提供骰子,甚至也可以由玩家來投擲骰子。

    你的任務是:通過編程模擬該過程。模擬50萬次,假定只有1個玩家,他每次的押注都是1元錢,其押注的匣子號是隨機的。再假定庄家有足夠的資金用於賠付。最后計算出庄家的盈率(庄家盈利金額/押注總金額)。


【輸入、輸出格式要求】

    程序無輸入,程序運行輸出庄家的盈率,四舍五入保留到小數后3位。

【注意】

    請仔細調試!您的程序只有能運行出正確結果的時候才有機會得分!
    
    請把所有類寫在同一個文件中,調試好后,存入與【考生文件夾】下對應題號的“解答.txt”中即可。
    
    相關的工程文件不要拷入。
    
    請不要使用package語句。
    
    源程序中只能出現JDK1.5中允許的語法或調用。不能使用1.6或更高版本。  

 

 1 public class Main {
 2     
 3     public boolean judge1(int[] A, int x) {
 4         for(int i = 0;i < A.length;i++)
 5             if(A[i] == x)
 6                 return true;
 7         return false;
 8     }
 9     
10     public boolean judge2(int[] A, int x) {
11         int count = 0;
12         for(int i = 0;i < A.length;i++)
13             if(A[i] == x)
14                 count++;
15         if(count >= 2)
16             return true;
17         return false;
18     }
19     
20     public boolean judge3(int[] A, int x) {
21         int count = 0;
22         for(int i = 0;i < A.length;i++)
23             if(A[i] == x)
24                 count++;
25         if(count == 3)
26             return true;
27         return false;
28     }
29     
30     public boolean judge4(int[] A, int x) {
31         if(x * A[0] == A[1] * A[2])
32             return true;
33         if(x * A[1] == A[0] * A[2])
34             return true;
35         if(x * A[2] == A[0] * A[1])
36             return true;
37         return false;
38     }
39     
40     public void getResult() {
41         double won = 0; 
42         for(int i = 1;i <= 500000;i++) {
43             int[] A = new int[3];
44             for(int j = 0;j < 3;j++)
45                 A[j] = (int) (Math.random() * 6) + 1;
46             int x = (int) (Math.random() * 6) + 1;
47             if(judge3(A, x)) {
48                 won -= 6;
49                 continue;
50             } else if(judge2(A, x)) {
51                 won -= 2;
52                 continue;
53             } else if(judge1(A, x)) {
54                 won -= 1;
55                 continue;
56             } else if(!judge4(A, x))
57                 won += 1;
58         }
59         won = won / 500000;
60         System.out.printf("%.3f", won);
61     }
62     
63     public static void main(String[] args) {
64         Main test = new Main();
65         test.getResult();
66     }
67 }

 

 


火柴游戲

 

【編程題】(滿分34分)

    這是一個縱橫火柴棒游戲。如圖[1.jpg],在3x4的格子中,游戲的雙方輪流放置火柴棒。其規則是:

    1. 不能放置在已經放置火柴棒的地方(即只能在空格中放置)。

    2. 火柴棒的方向只能是豎直或水平放置。

    3. 火柴棒不能與其它格子中的火柴“連通”。所謂連通是指兩根火柴棒可以連成一條直線,且中間沒有其它不同方向的火柴“阻攔”。

    例如:圖[1.jpg]所示的局面下,可以在C2位置豎直放置(為了方便描述格子位置,圖中左、下都添加了標記),但不能水平放置,因為會與A2連通。同樣道理,B2,B3,D2此時兩種方向都不可以放置。但如果C2豎直放置后,D2就可以水平放置了,因為不再會與A2連通(受到了C2的阻擋)。

    4. 游戲雙方輪流放置火柴,不可以棄權,也不可以放多根。直到某一方無法繼續放置,則該方為負(輸的一方)。

    游戲開始時可能已經放置了多根火柴。

    你的任務是:編寫程序,讀入初始狀態,計算出對自己最有利的放置方法並輸出。

    如圖[1.jpg]的局面表示為:

00-1
-000
0100

    即用“0”表示空閑位置,用“1”表示豎直放置,用“-”表示水平放置。

【輸入、輸出格式要求】
  
    用戶先輸入整數 n(n<100), 表示接下來將輸入 n 種初始局面,每種局面占3行(多個局面間沒有空白行)。

    程序則輸出:每種初始局面情況下計算得出的最佳放置法(行號+列號+放置方式)。

    例如:用戶輸入:
2
0111
-000
-000
1111
----
0010

   則程序可以輸出:
00-
211

   不難猜出,輸出結果的含義為:
   
   對第一個局面,在第0行第0列水平放置
   
   對第二個局面,在第2行第1列垂直放置

   注意:
   
   行號、列號都是從0開始計數的。
       
   對每種局面可能有多個最佳放置方法(解不唯一),只輸出一種即可。

   例如,對第一個局面,001 也是正解;最第二個局面,201也是正解。



【注意】

    請仔細調試!您的程序只有能運行出正確結果的時候才有機會得分!
    
    請把所有類寫在同一個文件中,調試好后,存入與【考生文件夾】下對應題號的“解答.txt”中即可。
    
    相關的工程文件不要拷入。
    
    請不要使用package語句。
    
    源程序中只能出現JDK1.5中允許的語法或調用。不能使用1.6或更高版本。  

 

  1 import java.util.Scanner;
  2 
  3 public class Main {
  4     public static String[] result;
  5     
  6     public char[] check(char[][] map, int i, int j) {
  7         char[] r = {'+', '+'};
  8         //檢測行
  9         boolean ring = true;
 10         if(j == 0) {
 11             if(map[i][j + 1] == '-' || (map[i][j + 1] == '0' && map[i][j + 2] == '-'))
 12                 ring = false;
 13         } else if(j == 1) {
 14             if(map[i][j - 1] == '-' || map[i][j + 1] == '-')
 15                 ring = false;
 16         } else if(j == 2) {
 17             if(map[i][j - 1] == '-' || (map[i][j - 1] == '0' && map[i][j - 2] == '-'))
 18                 ring = false;
 19         }
 20         //檢測列
 21         boolean row = true;
 22         if(i == 0) {
 23             if(map[i + 1][j] == '1' || (map[i + 1][j] == '0' && map[i + 2][j] == '1'))
 24                 row = false;
 25         } else if(i == 1) {
 26             if(map[i - 1][j] == '1' || map[i - 1][j] == '1')
 27                 row = false;
 28         } else if(i == 2) {
 29             if(map[i - 1][j] == '1' || (map[i - 1][j] == '0' && map[i - 2][j] == '1'))
 30                 row = false;
 31         }
 32         
 33         if(ring == true && row == true) {
 34             r[0] = '1';
 35             r[1] = '-';
 36         }
 37         if(ring == true && row == false) {
 38             r[0] = '-';
 39             r[1] = '+';
 40         }
 41         if(ring == false && row == true) {
 42             r[0] = '1';
 43             r[1] = '+';
 44         }
 45         if(ring == false && row == false){
 46             r[0] = '+';
 47             r[1] = '+';
 48         }
 49         return r;
 50     }
 51     
 52     public int getCount(char[][] tempMap) {
 53         int count = 0;
 54         for(int i = 0;i < 3;i++)
 55             for(int j = 0;j < 3;j++) {
 56                 char[] r = check(tempMap, i, j);
 57                 if(r[0] != '+')
 58                     count++;
 59             }
 60         return count;
 61     }
 62     
 63     public void getResult(char[][] map, int x) {
 64         char[][] tempMap = new char[3][3];
 65         int min = Integer.MAX_VALUE;
 66         for(int i = 0;i < 3;i++)
 67             for(int j = 0;j < 3;j++)
 68                 tempMap[i][j] = map[i][j];
 69         for(int i = 0;i < 3;i++) {
 70             for(int j = 0;j < 3;j++) {
 71                 if(map[i][j] == '0') {
 72                     char[] r = check(map, i, j);
 73                     for(int k = 0;k < 2;k++) {
 74                         if(r[k] != '+') {
 75                             tempMap[i][j] = r[k];
 76                             int count = getCount(tempMap);
 77                             tempMap[i][j] = '0';
 78                             if(count < min) {
 79                                 min = count;
 80                                 result[x] = "" + i+ j + r[k];
 81                             }
 82                         }
 83                     }
 84                 }
 85             }
 86         }
 87     }
 88     
 89     public static void main(String[] args) {
 90         Main test = new Main();
 91         Scanner in = new Scanner(System.in);
 92         int n = in.nextInt();
 93         result = new String[n];
 94         for(int i = 0;i < n;i++) {
 95             char[][] map = new char[3][3];
 96             String[] temp = new String[3];
 97             for(int j = 0;j < 3;j++) {
 98                 temp[j] = in.next();
 99                 map[j] = temp[j].toCharArray();
100             }
101             test.getResult(map, i);
102         }
103         for(int i = 0;i < result.length;i++)
104             System.out.println(result[i]);
105     }
106 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM