1  Fibonacci 

Fibonacci为1200年代的欧洲数学家,在他的著作中曾经提到:若有一只兔子每个月生一只小兔子,一个月后小兔子也开始生产。起初只有一只兔子,一个月后就有两只兔子,两个月后有三只兔子,三个月后有五只兔子(小兔子投入生产)…… 
这就是Fibonacci数列,一般习惯称之为费式数列,例如:1,1,2,3,5,8,13,21,34,55,89,…… 

 

java代码:

public class Fibonacci {
    public static void main(String[] args) {
        int[] fib = new int[20]; 
        fib[0] = 0; 
        fib[1] = 1; 
        for(int i = 2; i < fib.length; i++) 
            fib[i] = fib[i-1] + fib[i-2]; 
        for(int i = 0; i < fib.length; i++) 
            System.out.print(fib[i] + " "); 
        System.out.println();
    }
}

 

2   巴斯卡(Pascal) 

三角形基本上就是在解nCr ,因为三角形上的每一个数字各对应一个nCr ,其中n为row,而r为colnmu

 

java代码: 

import java.awt.*; 
import javax.swing.*; 
public class Pascal extends JFrame { 
    public Pascal() { 
        setBackground(Color.white); 
        setTitle("巴斯卡三角形"); 
        setSize(520, 350); 
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
        show(); 
    } 
    private long combi(int n, int r){ 
        int i; 
        long p = 1; 
        for(i = 1; i <= r; i++) 
            p = p * (n-i+1) / i; 
  
        return p; 
    } 
    public void paint(Graphics g) { 
        final int N = 12; 
        int n, r, t; 
        for(n = 0; n <= N; n++) { 
            for(r = 0; r <= n; r++) 
                g.drawString(" " + combi(n, r), 
                    (N-n)*20 + r * 40, n * 20 + 50); 
        } 
    } 
    public static void main(String args[]) { 
        Pascal frm = new Pascal(); 
    } 
}

3  ThreeColorFlags 


ThreeColorFlags问题最早由E.W.Dijkstra所提出,塔所使用的用语为Dutch Nation Flag(Dijkstra为荷兰人),而多数的作者则使用Three-Color Flag来说明。 

假设有一条绳子,上面有红,白,蓝三种颜色的旗子,起初绳子上的旗子颜色并没有顺序,您希望将之分类,并排列蓝,白,红的顺序,要如何移动次数才会最少,注意您只能在绳子上进行这个动作,而且一次只能调换两个旗子。

 

java代码:

import java.io.*;
public class ThreeColorsFlags {
    private void swap(char[] flags, int x, int y) {
        char temp;
        temp = flags[x];
        flags[x] = flags[y];
        flags[y] = temp;
    }
    
    public String move(char[] flags) {
        int wFlag = 0;
        int bFlag = 0;
        int rFlag = flags.length - 1;
    
        while(wFlag <= rFlag) {
            if(flags[wFlag] == 'W') {
                wFlag++;
            }
            else if(flags[wFlag] == 'B') {
                swap(flags, bFlag, wFlag);
                bFlag++;
                wFlag++;
            }
            else {
                while(wFlag < rFlag && flags[rFlag] == 'R')
                    rFlag--;
                swap(flags, rFlag, wFlag);
                rFlag--;                
            }
        }
        
        return new String(flags);
    }
    
    public static void main(String[] args) 
                                throws IOException {        
        BufferedReader buf; 
        buf = new BufferedReader(
                    new InputStreamReader(System.in)); 
        System.out.print("输入三色旗顺序(ex. RWBBWRWR):");
        String flags = buf.readLine();
        
        ThreeColorsFlags threeColorsFlag = new ThreeColorsFlags();
        flags = threeColorsFlag.move(
                   flags.toUpperCase().toCharArray());
        
        System.out.println("移动顺序后:" + flags);        
    }
}

 

4 Mouse 


Mouse走迷宫是循环求解的基本类型,我们在二维数组中用2来表示迷宫的墙壁,使用1来表示老鼠的行走路径,并用程序求出从入口到出口的距离。

 

java代码:

public class Mouse {
    private int startI, startJ;  // 入口 
    private int endI, endJ;  // 出口
    private boolean success = false;
    
    public static void main(String[] args) {
        int[][] maze = {{2, 2, 2, 2, 2, 2, 2}, 
                        {2, 0, 0, 0, 0, 0, 2}, 
                        {2, 0, 2, 0, 2, 0, 2}, 
                        {2, 0, 0, 2, 0, 2, 2}, 
                        {2, 2, 0, 2, 0, 2, 2}, 
                        {2, 0, 0, 0, 0, 0, 2}, 
                        {2, 2, 2, 2, 2, 2, 2}};
        
        System.out.println("显示迷宫:"); 
        for(int i = 0; i < maze.length; i++) { 
            for(int j = 0; j < maze[0].length; j++) 
                if(maze[j] == 2) 
                    System.out.print("█"); 
                else 
                    System.out.print("  "); 
            System.out.println(); 
        }
        Mouse mouse = new Mouse();
        mouse.setStart(1, 1);
        mouse.setEnd(5, 5);
        
        if(!mouse.go(maze)) {
            System.out.println("/n没有找到出口!");
        }
        else {
            System.out.println("/n找到出口!");
            for(int i = 0; i < maze.length; i++) { 
                for(int j = 0; j < maze[0].length; j++) { 
                    if(maze[j] == 2) 
                        System.out.print("█"); 
                    else if(maze[j] == 1) 
                        System.out.print("◇"); 
                    else 
                        System.out.print("  "); 
                } 
                System.out.println(); 
            }            
        }
    }
    
    public void setStart(int i, int j) {
        this.startI = i;
        this.startJ = j;
    }
    
    public void setEnd(int i, int j) {
        this.endI = i;
        this.endJ = j;
    }
    
    public boolean go(int[][] maze) {
        return visit(maze, startI, startJ);
    }
    
    private boolean visit(int[][] maze, int i, int j) {
        maze[j] = 1; 
        if(i == endI && j == endJ) 
            success = true; 
        if(!success && maze[j+1] == 0) 
            visit(maze, i, j+1); 
        if(!success && maze[i+1][j] == 0)
            visit(maze, i+1, j); 
        if(!success && maze[j-1] == 0)
            visit(maze, i, j-1); 
        if(!success && maze[i-1][j] == 0)
            visit(maze, i-1, j); 
        if(!success) 
            maze[j] = 0; 
        
        return success; 
    }
}

 

5 Knight tour 


骑士游戏,在十八世纪倍受数学家与拼图迷的注意,骑士的走法为西洋棋的走发,骑士可以由任何一个位置出发,它要如何走完所有的位置。

 

java代码: 

public class Knight {
    public boolean travel(int startX, 
                          int startY, int[][] board) {
        // 对应骑士可以走的八个方向
        int[] ktmove1 = {-2, -1, 1, 2, 2, 1, -1, -2};
        int[] ktmove2 = {1, 2, 2, 1, -1, -2, -2, -1};
        
        // 下一个出路的位置         int[] nexti = new int[board.length];
        int[] nextj = new int[board.length];
        
        // 记录出路的个数
        int[] exists = new int[board.length];
        
        int x = startX;
        int y = startY;
        
        board[x][y] = 1;
        
        for(int m = 2; m <= Math.pow(board.length, 2); m++) {
            for(int k = 0; k < board.length; k++) {
                exists[k] = 0;
            }
            
            int count = 0;
            // 试探八个方向
            for(int k = 0; k < board.length; k++) {
                int tmpi = x + ktmove1[k];
                int tmpj = y + ktmove2[k];
                
                // 如果是边界,不可以走
                if(tmpi < 0 || tmpj < 0 || 
                   tmpi > 7 || tmpj > 7) {
                    continue;
                }
                
                // 如果这个方向可以走,记录下来
                if(board[tmpi][tmpj] == 0) {
                    nexti[count] = tmpi;
                    nextj[count] = tmpj;
                    // 可走的方向加一个
                    count++;
                }
            }
            
            int min = -1;
            if(count == 0) {
                return false;
            }
            else if(count == 1) {
                min = 0;
            }
            else {
                // 找出下个位置的出路数
                for(int l = 0; l < count; l++) {
                    for(int k = 0; k < board.length; k++) {
                        int tmpi = nexti[l] + ktmove1[k];
                        int tmpj = nextj[l] + ktmove2[k];
                        if(tmpi < 0 || tmpj < 0 || 
                           tmpi > 7 || tmpj > 7) {
                            continue;
                        }
                        if(board[tmpi][tmpj] == 0)
                            exists[l]++;
                    }
                }
                int tmp = exists[0];
                min = 0;
                // 从可走的方向寻找最少出路的方向
                for(int l = 1; l < count; l++) {
                    if(exists[l] < tmp) {
                        tmp = exists[l];
                        min = l;
                    }
                }
            }
            
            // 走最少出路的方向
            x = nexti[min];
            y = nextj[min];
            board[x][y] = m;
        }
        
        return true;
    }
    
    public static void main(String[] args) {
        int[][] board = new int[8][8];
        Knight knight = new Knight();
        
        if(knight.travel(
                Integer.parseInt(args[0]), 
                Integer.parseInt(args[1]), board)) {
            System.out.println("走棋完成!");
        }
        else {
            System.out.println("走棋失败!");
        }
        
        for(int i = 0; i < board.length; i++) {
            for(int j = 0; j < board[0].length; j++) {
                if(board[i][j] < 10) {
                    System.out.print(" " + board[i][j]);
                }
                else {
                    System.out.print(board[i][j]);
                }
                System.out.print(" ");
            }
            System.out.println();
        }
    }
}

 

 

6 Queen 


西洋棋中的皇后可以直线前进,吃掉遇到的所有棋子,如果棋盘上有八个皇后,则这八个皇后如何相安无事的放置在棋盘上?

 

java代码: 

public class Queen {
    // 同位置是否有皇后,1表示有 
    private int[] column;
    // 右上至左下是否有皇后
    private int[] rup; 
    // 左上至右下是否有皇后
    private int[] lup;
    // 解答
    private int[] queen;
    
    // 解答编号
    private int num;
    
    public Queen() {
        column = new int[8+1];
        rup = new int[2*8+1];
        lup = new int[2*8+1];
        
        for(int i = 1; i <= 8; i++) 
            column[i] = 1; 
        for(int i = 1; i <= 2*8; i++) 
            rup[i] = lup[i] = 1; 
        
        queen = new int[8+1];
    }
    
    public void backtrack(int i) {
        if(i ><IMG src="/images/smiles/icon_cool.gif" mce_src="images/smiles/icon_cool.gif">{ 
            showAnswer();
        } 
        else { 
            for(int j = 1; j <= 8; j++) { 
                if(column[j] == 1 && 
                   rup[i+j] == 1 && 
                   lup[i-j+8] == 1) { 
                    queen[i] = j; 
                    // 设定为占用
                    column[j] = rup[i+j] = lup[i-j+8] = 0; 
                    backtrack(i+1); 
                    column[j] = rup[i+j] = lup[i-j+8] = 1; 
                } 
            } 
        } 
    }
    
    protected void showAnswer() {
        num++;
        System.out.println("/n解答 " + num);
        for(int y = 1; y <= 8; y++) {
            for(int x = 1; x <= 8; x++) {
                if(queen[y] == x) {
                    System.out.print(" Q");
                }
                else {
                    System.out.print(" .");
                }
            }
            System.out.println();
        }
    }
    
    public static void main(String[] args) {
        Queen queen = new Queen();
        queen.backtrack(1);
    }
}

7  Coins 


现在有八枚银币abcdefg,已知其中一枚是假币,其重量不同于真币,但不知道是轻还是重,如何用天平以最小的比较次数决定出那个是假币,并得知假币是比真币轻还是重。 

 

java代码:

public class Coins {
    private int[] coins;
    
    public Coins() {
        coins = new int[8];
        for(int i = 0; i < 8; i++) 
            coins[i] = 10; 
    }
    
    public void setFake(int weight) {
        coins[(int) (Math.random() * 7)] = weight;
    }
    
    public void fake() {
        if(coins[0]+coins[1]+coins[2] == 
           coins[3]+coins[4]+coins[5]) { 
            if(coins[6] > coins[7]) 
                compare(6, 7, 0); 
            else 
                compare(7, 6, 0); 
        } 
        else if(coins[0]+coins[1]+coins[2] > 
                coins[3]+coins[4]+coins[5]) { 
            if(coins[0]+coins[3] == coins[1]+coins[4]) 
                compare(2, 5, 0); 
            else if(coins[0]+coins[3] > coins[1]+coins[4]) 
                compare(0, 4, 1); 
            if(coins[0]+coins[3] < coins[1]+coins[4]) 
                compare(1, 3, 0); 
        } 
        else if(coins[0]+coins[1]+coins[2] < 
                coins[3]+coins[4]+coins[5]) { 
            if(coins[0]+coins[3] == coins[1]+coins[4]) 
                compare(5, 2, 0); 
            else if(coins[0]+coins[3] > coins[1]+coins[4]) 
                compare(3, 1, 0); 
            if(coins[0]+coins[3] < coins[1]+coins[4]) 
                compare(4, 0, 1); 
        } 
    }
    
    protected void compare(int i, int j, int k) {
        if(coins[i] > coins[k]) 
            System.out.print("/n假币 " + (i+1) + " 较重"); 
        else 
            System.out.print("/n假币 " + (j+1) + " 较轻"); 
    }
    
    public static void main(String[] args) {
        if(args.length == 0) {
            System.out.println("输入假币重量(比10大或小)");
            System.out.println("ex. java Coins 5");
            return;
        }
        
        Coins eightCoins = new Coins();
        eightCoins.setFake(Integer.parseInt(args[0]));
        eightCoins.fake();
    }
}

 

 

8  Life game 


生命游戏,为1970年英国数学家J.H.Conway所提出,某一细胞的邻居包括上,下,左,右,左上,左下,右上与右下相邻的细胞,游戏规则如下: 

1,孤单死亡:如果细胞的邻居小于一个,则该细胞在下一个状态死亡。 

2,拥挤死亡:如果细胞的邻居在四个以上,则该细胞在下一个状态死亡。 

3,稳定:如果细胞的邻居为两个或三个,则该细胞在下一个状态稳定。 

4,复活:如果某位置原无细胞存活,而该位置的邻居为三个,则该位置将复活一个细胞。 

 

java代码:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class LifeGame {
    private boolean[][] map;
    private boolean[][] newmap;
    
    public LifeGame(int maxRow, int maxColumn) {
        map = new boolean[maxRow][maxColumn];
        newmap = new boolean[maxRow][maxColumn];
    }
    
    public void setCell(int x, int y) {
        map[x][y] = true;
    }
    
    public void next() {
        for(int row = 0; row < map.length; row++) {
            for(int col = 0; col < map[0].length; col++) {
               switch (neighbors(row, col)) {
                  case 0: 
                  case 1: 
                  case 4: 
                  case 5: 
                  case 6: 
                  case 7: 
                  case 8: 
                     newmap[row][col] = false; 
                     break; 
                  case 2: 
                     newmap[row][col] = map[row][col]; 
                     break; 
                  case 3: 
                     newmap[row][col] = true; 
                     break; 
               } 
            }
         }
         copyMap();
    }
    public void outputMap() throws IOException { 
        System.out.println("/n/nGame of life cell status"); 
        for(int row = 0; row < map.length; row++) { 
            System.out.print("/n "); 
           for(int col = 0; col < map[0].length; col++) 
              if(map[row][col] == true) 
                  System.out.print('#'); 
              else 
                  System.out.print('-'); 
        } 
    }
    
    private void copyMap() {
        for(int row = 0; row < map.length; row++) 
           for(int col = 0; col < map[0].length; col++) 
              map[row][col] = newmap[row][col]; 
    }
    
    private int neighbors(int row, int col) {
        int count = 0; 
        for(int r = row-1; r <= row+1; r++) 
           for(int c = col-1; c <= col+1; c++) { 
              if(r < 0 || r >= map.length ||
                 c < 0 || c >= map[0].length) 
                 continue; 
              if(map[r][c] == true) 
                 count++; 
           } 
        if(map[row][col] == true) 
           count--; 
         
        return count; 
    } 
    
    public static void main(String[] args) 
                 throws NumberFormatException, IOException {
        BufferedReader bufReader = 
            new BufferedReader(
                    new InputStreamReader(System.in));
        
        LifeGame game = new LifeGame(10, 25);
        
        System.out.println("Game of life Program"); 
        System.out.println(
                   "Enter x, y where x, y is living cell");
        System.out.println("0 <= x < 10, 0 <= y < 25"); 
        System.out.println("Terminate with x, y = -1, -1");
        
        while(true) {
            String[] strs = bufReader.readLine().split(" ");
            int row = Integer.parseInt(strs[0]);
            int col = Integer.parseInt(strs[1]);
            if(0 <= row && row < 10 && 0 <= col && row < 25) 
                game.setCell(row, col);
            else if(row == -1 || col == -1) {
                break;
            }
            else { 
                System.out.print(
                         "(x, y) exceeds map ranage!");
            }
        }
        
        while(true) {
            game.outputMap();
            game.next();
            System.out.print(
                         "/nContinue next Generation ? ");
            
            String ans = bufReader.readLine().toUpperCase();
            if(!ans.equals("Y"))
                break;
        } 
    }
}

 

 

9  String Match 


现在的一些高级程序语言对于字符串的处理支持越来越大,不过字符串搜寻本身仍是值得探讨的课题,在这里以Boyer Moore法来说明如何进行字符串说明,这个方法速度快且容易理解。 

 

java代码:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class StringMatch {
    private int[] skip;
    private int p;
    private String str;
    private String key;
    
    public StringMatch(String key) {
        skip = new int[256];
        this.key = key;
        
        for(int k = 0; k <= 255; k++) 
            skip[k] = key.length(); 
        for(int k = 0; k < key.length() - 1; k++) 
            skip[key.charAt(k)] = key.length() - k - 1; 
    }
    
    public void search(String str) {
        this.str = str;
        p = search(key.length()-1, str, key);
    }
    
    private int search(int p, String input, String key) {   
        while(p < input.length()) { 
            String tmp = input.substring(
                                p-key.length()+1, p+1); 
            if(tmp.equals(key))  // 比较两个字符串是否相同 
               return p-key.length()+1; 
            p += skip[input.charAt(p)]; 
        } 
        return -1; 
    }
    
    public boolean hasNext() {
        return (p != -1);
    }
    
    public String next() {
        String tmp = str.substring(p);
        p = search(p+key.length()+1, str, key);
        return tmp;
    }
    
    public static void main(String[] args) 
                                      throws IOException {
        BufferedReader bufReader = 
            new BufferedReader(
                    new InputStreamReader(System.in));
        
        System.out.print("请输入字符串:");
        String str = bufReader.readLine();
        System.out.print("请输入搜寻关键字:"); 
        String key = bufReader.readLine();
        
        StringMatch strMatch = new StringMatch(key);
        strMatch.search(str);
        while(strMatch.hasNext()) { 
            System.out.println(strMatch.next()); 
        } 
    }
}

 

 

10  Kanpsack Problem 


假设一个背包的负重最大可达8公斤,而希望在背包内放置负重范围你价值最高的物品。

 

java代码:

class Fruit {
    private String name;
    private int size;
    private int price;
    
    public Fruit(String name, int size, int price) {
        this.name = name;
        this.size = size;
        this.price = price;
    }
    
    public String getName() {
        return name;
    }
    public int getPrice() {
        return price;
    }
    public int getSize() {
        return size;
    }
}
public class Knapsack {
    public static void main(String[] args) {
        final int MAX = 8;
        final int MIN = 1;
        int[] item = new int[MAX+1]; 
        int[] value = new int[MAX+1];  
        Fruit fruits[] = {
                new Fruit("李子", 4, 4500), 
                new Fruit("苹果", 5, 5700), 
                new Fruit("桔子", 2, 2250), 
                new Fruit("草莓", 1, 1100), 
                new Fruit("甜瓜", 6, 6700)}; 
        for(int i = 0; i < fruits.length; i++) { 
            for(int s = fruits[i].getSize(); s <= MAX; s++) { 
                int p = s - fruits[i].getSize(); 
                int newvalue = value[p] + 
                                   fruits[i].getPrice(); 
                if(newvalue > value[s]) {// 找到阶段最佳解 
                    value[s] = newvalue; 
                    item[s] = i; 
                } 
            } 
        } 
        System.out.println("物品/t价格"); 
        for(int i = MAX; 
            i >= MIN; 
            i = i - fruits[item[i]].getSize()) { 
            System.out.println(fruits[item[i]].getName()+ 
                    "/t" + fruits[item[i]].getPrice()); 
        } 
        System.out.println("合计/t" + value[MAX]);  
    }
}

 

 

 

11  Towers of Hanoi 

河內之塔(Towers of Hanoi)是法国人M.Claus(Lucas)於1883年从泰国带至法国的,河內为越战时北越的首都,即现在的胡志明市;1883年法国数学家 Edouard Lucas曾提及這个故事,据说创世紀时Benares有一座波罗教塔,是由三支钻石棒(Pag)所支撑,开始时神在第一根棒上放置64个由上至下依由小至大排列的金盘(Disc),並命令僧侣将所有的金盘从第一根石棒移至第三根石棒,且搬运过程中遵守大盘子在小盘子之下的原则,若每日仅搬一个盘子,则当盘子全数搬运完毕之时,此塔将损毁,而也就是世界末日來临之时。

 

java代码:

import java.io.*;
public class Hanoi {
    public static void main(String args[]) throws IOException {
        int n;
        BufferedReader buf;
        buf = new BufferedReader(new InputStreamReader(System.in));
        System.out.print("请输入盘子个数");
        n = Integer.parseInt(buf.readLine());
        Hanoi hanoi = new Hanoi();
        hanoi.move(n, 'A', 'B', 'C');
    }
    public void move(int n, char a, char b, char c) {
        if(n == 1)
            System.out.println("盘 " + n + " 由 " + a + " 移至 " + c);
        else {
            move(n - 1, a, c, b);
            System.out.println("盘 " + n + " 由 " + a + " 移至 " + c);
            move(n - 1, b, a, c);
        }
    }
}

 

12  Hanoi2Colors 


Hanoi2Colors是由河内塔演变而来的一种算法。

 

java代码:

public class Hanoi2Colors { 
    public static void help() {
        System.out.println(
              "Usage: java Hanoi2Colors number_of_disks");
        System.out.println(
              "/t number_of_disks: must be a even number.");
        System.exit(0);
    }
    
    public static void main(String[] args) {
        int disks = 0;        
        try {
            disks = Integer.parseInt(args[0]);
        } catch (Exception e) {
            help();
        }
        if ((disks <= 0) || (disks % 2 != 0)) { 
            help(); 
        }
        hanoi2colors(disks);
    }
     
    public static void hanoi(int disks, 
                      char source, char temp, char target) {
        if (disks == 1) {
            System.out.println("move disk from " 
                               + source + " to " + target);
            System.out.println("move disk from " 
                               + source + " to " + target);
        } else {        
            hanoi(disks-1, source, target, temp);
            hanoi(1, source, temp, target);
            hanoi(disks-1, temp, source, target);
        }
    }
    public static void hanoi2colors(int disks) {
        char source = 'A';
        char temp = 'B';
        char target = 'C';
        for (int i = disks / 2; i > 1; i--) {
            hanoi(i-1, source, temp, target);
            System.out.println("move disk from " 
                                   + source + " to " + temp);
            System.out.println("move disk from " 
                                   + source + " to " + temp); 
            hanoi(i-1, target, temp, source);
            System.out.println("move disk from " 
                                   + temp + " to " + target);
        }
        System.out.println("move disk from " 
                                   + source + " to " + temp);
        System.out.println("move disk from " 
                                 + source + " to " + target);
    }
}