2013年5月10日 星期五

簡單校園導覽程式

Java code:
import java.util.Arrays;
import java.util.Scanner;

public class FjuMap {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int startVertex;
        int endVertex;
        String[] names = {"利瑪竇大樓", "伯達樓", "樹德樓", "羅耀拉大樓", "濟時樓", "仁愛學苑", "聖心學苑", "信義/和平學苑/心園", "法園(社會服務中心)/仁園", "創新育成中心"};
        int[][] path = new int[10][10];
        int[][] graph =
                {{0, 13, Integer.MAX_VALUE, 25, Integer.MAX_VALUE, 27, Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE},
                {13, 0, 10 , 20, Integer.MAX_VALUE, 35, Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE},
                {Integer.MAX_VALUE, 10, 0, 12, Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE},
                {25, 20, 12, 0, 20, 22, Integer.MAX_VALUE, 28, 27, Integer.MAX_VALUE},
                {Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, 20, 0, 25, Integer.MAX_VALUE, Integer.MAX_VALUE, 16, Integer.MAX_VALUE},
                {27, 35, Integer.MAX_VALUE, 22, 25, 0, 9, 9, Integer.MAX_VALUE, Integer.MAX_VALUE},
                {Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, 9, 0, 8, Integer.MAX_VALUE, Integer.MAX_VALUE},
                {Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, 28, Integer.MAX_VALUE, 9, 8, 0, 10, 12},
                {Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, 27, 16, Integer.MAX_VALUE, Integer.MAX_VALUE, 10, 0, 7},
                {Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, 12, 7, 0}};
        
        for (int[] i: path)
            Arrays.fill(i, -1);
        for (int i=0; i<graph.length; i++) {
            for (int j=0; j<graph.length; j++) {
                for (int k=0; k<graph.length; k++) {
                    if (!(graph[i][k] == Integer.MAX_VALUE) && !(graph[k][j] == Integer.MAX_VALUE)) {
                        int newWeight = graph[i][k] + graph[k][j];
                        
                        if (newWeight < graph[i][j]) {
                            graph[i][j] = newWeight;
                            path[i][j] = k;
                        }
                    }
                }
            }
        }
        System.out.println("地點清單:");
        System.out.println("-----------------------");
        for (int i=0; i<names.length; i++)
        System.out.println(i + "." + names[i]);
        System.out.println("-----------------------");
        try {
            while (true) {
                System.out.print("請輸入起點編號(輸入10結束):");
                startVertex = sc.nextInt();
                if (startVertex == 10)
                    break;
                System.out.print("請輸入終點編號:");
                endVertex = sc.nextInt();
                System.out.print("最短路徑:");
                System.out.print(names[startVertex]);
                tracePath(path, names, startVertex, endVertex);
                System.out.println("->" + names[endVertex] + "\n");
            }
        } finally {
            sc.close();
        }
    }

    private static void tracePath(int[][] path, String[] names, int startVertex, int endVertex) {
        if (path[startVertex][endVertex] != -1) {
            tracePath(path, names, startVertex, path[startVertex][endVertex]);
            System.out.print("->" + names[path[startVertex][endVertex]]);
            tracePath(path, names, path[startVertex][endVertex], endVertex);
        }
    }
}

範例輸入輸出:



抱歉沒空說明程式碼,只能說明一下輸入輸出的部份。首先依照地點清單輸入起點編號,再輸入終點編號,程式就會印出最短路徑,若在起點編號那裡輸入10,程式就會結束。

2013年5月9日 星期四

Dijkstra's Algorithm

Java code:
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;

public class DijkstraAlgorithm {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int vertexNum;
        Set<Integer> used = new HashSet<Integer>();
        Map<Integer, Map<Integer, Integer>> graph = new HashMap<Integer, Map<Integer, Integer>>();
        Map<Integer, Integer> shortestPath = new HashMap<Integer, Integer>();
        int startVertex;
        
        try {
            System.out.print("please input the number of total vertexes:");
            vertexNum = sc.nextInt();
            System.out.println("please input the graph:");
            for (int i=1; i<=vertexNum; i++)
                graph.put(i, new HashMap<Integer, Integer>());
            for (int i=1; i<=vertexNum; i++) {
                for (int j=1; j<=vertexNum; j++) {
                    String input = sc.next();
                    
                    if (input.equals("i"))
                        graph.get(i).put(j, Integer.MAX_VALUE);
                    else
                        graph.get(i).put(j, Integer.parseInt(input));
                }
            }
            System.out.print("please input the start vertex:");
            startVertex = sc.nextInt();
        } finally {
            sc.close();
        }
        for (int i=1; i<=vertexNum; i++)
            shortestPath.put(i, graph.get(startVertex).get(i));
        used.add(startVertex);
        while (true) {
            int nearestVertex = -1;
            int smallestWeight = Integer.MAX_VALUE;
            
            for (int i=1; i<=vertexNum; i++) {
                if (!used.contains(i) && shortestPath.get(i) < smallestWeight) {
                    nearestVertex = i;
                    smallestWeight = shortestPath.get(i);
                }
            }
            used.add(nearestVertex);
            if (used.size() == vertexNum)
                break;
            for (int i=1; i<=vertexNum; i++) {
                if (graph.get(nearestVertex).get(i) != 0 && graph.get(nearestVertex).get(i) != Integer.MAX_VALUE) {
                    int newPath = shortestPath.get(nearestVertex) + graph.get(nearestVertex).get(i);
                    
                    if (newPath < shortestPath.get(i))
                        shortestPath.put(i, newPath);
                }
            }
        }
        System.out.println("shortest path from v" + startVertex + " to all other vertexes:");
        for (int i=1; i<=vertexNum; i++)
            System.out.printf("%4s", "v" + i);
        System.out.println();
        for (int i=1; i<=vertexNum; i++)
            System.out.printf("%4d", shortestPath.get(i));
        System.out.println();
    }
}

範例輸入輸出:



抱歉沒空說明程式碼,只能說明一下輸入輸出的部份。首先輸入圖形上總共點的數量,再輸入相鄰矩陣,橫軸表示點1~點10,縱軸也是表示點1~點10,輸入的是點到點之間的權重,若輸入i表示這兩點不相連,也就是權重無限大,最後再輸入以哪個點當作起點,程式會找出由這個點到其他所有點的最短距離。輸出結果表示由出發點到各點的距離。本範例輸入是採用課本習題2的圖,所以可以參照課本的圖方便了解。

Kruskal's Algorithm

Java code:
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;

class Edge implements Comparable<Edge> {
    int startVertex, endVertex, weight;

    @Override
    public int compareTo(Edge otherEdge) {
        if (weight < otherEdge.weight)
            return -1;
        else if (weight == otherEdge.weight)
            return 0;
        else
            return 1;
    }
}

public class KruskalAlgorithm {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int vertexNum;
        int countEdge;
        int totalEdge;
        List<Edge> allEdgeList = new ArrayList<Edge>();
        Map<Integer, Map<Integer, Integer>> minSpanTree = new HashMap<Integer, Map<Integer, Integer>>();
        
        try {
            System.out.print("please input the number of total vertexes:");
            vertexNum = sc.nextInt();
            System.out.println("please input the graph:");
            for (int i=1; i<=vertexNum; i++) {
                for (int j=1; j<=vertexNum; j++) {
                    String theWeight = sc.next();
                    
                    if (!theWeight.equals("i") && i < j) {
                        Edge theEdge = new Edge();
                        
                        theEdge.startVertex = i;
                        theEdge.endVertex = j;
                        theEdge.weight = Integer.parseInt(theWeight);
                        allEdgeList.add(theEdge);
                    }
                }    
            }
        } finally {
            sc.close();
        }
        for (int i=1; i<=vertexNum; i++) {
            minSpanTree.put(i, new HashMap<Integer, Integer>());
            for (int j=1; j<=vertexNum; j++)
                minSpanTree.get(i).put(j, Integer.MAX_VALUE);
        }
        Collections.sort(allEdgeList);
        countEdge = 0;
        totalEdge = vertexNum - 1;
        while (countEdge != totalEdge) {
            Edge smallestEdge = allEdgeList.remove(0);
            
            if (!checkCycle(minSpanTree, vertexNum, smallestEdge.startVertex, smallestEdge.startVertex, smallestEdge.endVertex)) {
                minSpanTree.get(smallestEdge.startVertex).put(smallestEdge.endVertex, smallestEdge.weight);
                minSpanTree.get(smallestEdge.endVertex).put(smallestEdge.startVertex, smallestEdge.weight);
                countEdge++;
            }
        }
        System.out.println("the minimal spanning tree:");
        for (int i=1; i<=vertexNum; i++) {
            for (int j=1; j<=vertexNum; j++) {
                if (minSpanTree.get(i).get(j) == Integer.MAX_VALUE)
                    System.out.printf("%3s", "i");
                else
                    System.out.printf("%3d", minSpanTree.get(i).get(j));
            }
            System.out.println();
        }
    }
    
    private static boolean checkCycle(Map<Integer, Map<Integer, Integer>> minSpanTree, int vertexNum, int originalVertex, int preVertex, int nowVertex) {
        if (originalVertex == nowVertex)
            return true;
        else {
            for (int i=1; i<=vertexNum; i++) {
                if (minSpanTree.get(nowVertex).get(i) != Integer.MAX_VALUE && i != preVertex && checkCycle(minSpanTree, vertexNum, originalVertex, nowVertex, i))
                    return true;
            }
            return false;
        }
    }
}

範例輸入輸出:



抱歉沒空說明程式碼,只能說明一下輸入輸出的部份。首先輸入圖形上總共點的數量,再輸入相鄰矩陣,橫軸表示點1~點10,縱軸也是表示點1~點10,輸入的是點到點之間的權重,若輸入i表示這兩點不相連,也就是權重無限大。輸出結果也是相鄰矩陣,表示找到的最小成本擴展樹。本範例輸入是採用課本習題2的圖,所以可以參照課本的圖方便了解。

Prim's Algorithm

Java code:
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Scanner;
import java.util.Set;

class Edge {
    int startVertex, endVertex, weight;
}

class PriQueueComparator implements Comparator<Edge> {

    @Override
    public int compare(Edge thisEdge, Edge otherEdge) {
        if (thisEdge.weight < otherEdge.weight)
            return -1;
        else if (thisEdge.weight == otherEdge.weight)
            return 0;
        else
            return 1;
    }
}

public class PrimAlgorithm {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int vertexNum;
        int nextVertex;
        Set<Integer> used = new HashSet<Integer>();
        Map<Integer, Map<Integer, Integer>> graph = new HashMap<Integer, Map<Integer, Integer>>();
        Map<Integer, Map<Integer, Integer>> minSpanTree = new HashMap<Integer, Map<Integer, Integer>>();
        Queue<Edge> priQueue;
        
        try {
            System.out.print("please input the number of total vertexes:");
            vertexNum = sc.nextInt();
            priQueue = new PriorityQueue<Edge>(vertexNum - 1, new PriQueueComparator());
            System.out.println("please input the graph:");
            for (int i=1; i<=vertexNum; i++)
                graph.put(i, new HashMap<Integer, Integer>());
            for (int i=1; i<=vertexNum; i++) {
                for (int j=1; j<=vertexNum; j++) {
                    String input = sc.next();
                    
                    if (input.equals("i"))
                        graph.get(i).put(j, Integer.MAX_VALUE);
                    else
                        graph.get(i).put(j, Integer.parseInt(input));
                }
            }
        } finally {
            sc.close();
        }
        for (int i=1; i<=vertexNum; i++) {
            minSpanTree.put(i, new HashMap<Integer, Integer>());
            for (int j=1; j<=vertexNum; j++)
                minSpanTree.get(i).put(j, Integer.MAX_VALUE);
        }
        nextVertex = 1;
        while (true) {
            Edge smallestEdge;
            
            used.add(nextVertex);
            if (used.size() == vertexNum)
                break;
            for (int i=1; i<=vertexNum; i++) {
                Edge theEdge = new Edge();
                
                if (graph.get(nextVertex).get(i) != Integer.MAX_VALUE) {
                    theEdge.startVertex = nextVertex;
                    theEdge.endVertex = i;
                    theEdge.weight = graph.get(nextVertex).get(i);
                    priQueue.add(theEdge);
                }
            }
            while (true) {
                smallestEdge = priQueue.poll();
                if (!used.contains(smallestEdge.endVertex))
                    break;
            }
            minSpanTree.get(smallestEdge.startVertex).put(smallestEdge.endVertex, smallestEdge.weight);
            minSpanTree.get(smallestEdge.endVertex).put(smallestEdge.startVertex, smallestEdge.weight);
            nextVertex = smallestEdge.endVertex;
        }
        System.out.println("minimal spanning tree");
        for (int i=1; i<=vertexNum; i++) {
            for (int j=1; j<=vertexNum; j++) {
                if (minSpanTree.get(i).get(j) == Integer.MAX_VALUE)
                    System.out.printf("%3s", "i");
                else
                    System.out.printf("%3d", minSpanTree.get(i).get(j));
            }
            System.out.println();
        }
    }
}

範例輸入輸出:



抱歉沒空說明程式碼,只能說明一下輸入輸出的部份。首先輸入圖形上總共點的數量,再輸入相鄰矩陣,橫軸表示點1~點10,縱軸也是表示點1~點10,輸入的是點到點之間的權重,若輸入i表示這兩點不相連,也就是權重無限大。輸出結果也是相鄰矩陣,表示找到的最小成本擴展樹。本範例輸入是採用課本習題2的圖,所以可以參照課本的圖方便了解。

2013年5月6日 星期一

10156 - Sala-ma-Sond, A Nice Little Pond


The Problem

Of course, the turtles aren't completely free. In particular, they aren't free to swim where other turtles are swimming. To learn more about the swimming behaviour of turtles you decide to write a computer simulation of a pond and the turtles swimming in it.
For simplicity, you represent the pond as a rectangular grid, with turtles occupying positions at points on the grid. If the pond is an NxM grid, a position on the grid may be represented by a pair of integer coordinates (i, j), with 0 <= i < N and 0 <= j < M. The grid is aligned with its first dimension running north-south and its second dimension running east-west. Coordinate values increase to the south and the east.
A turtle swimming in the pond may be requested to move to the adjacent grid position in one of eight directions: N, S, E, W, NE, NW, SE, SW. If the request would cause the turtle to move off the grid or cause it to move onto a grid position occupied by another turtle, the request is ignored. Otherwise, the turtle happily obeys the movement request. (Turtles are easy to push around.)
The input consist of several data sets. Each data set begins with a description of the pond and the initial location of the turtles. The first line of the input consists of four integers separated by one or more spaces. The first integer specifies the size of the pond in the north-south direction (N), the second integer specifies the size of the pond in the east-west direction (M), the third integer specifies the number of turtles in the pond (T) and the fourth integer indicates the number of turtle movement requests (K). This first line is followed by T lines, each providing information on a single turtle. Each line of turtle information consists of three integers separated by one or more spaces. The first integer specifies a turtle id, the second integer specifies an initial grid position for the turtle along the north-south dimension, and the third integer specifies an initial grid position for the turtle along the east-west dimension. All turtles will be located at valid grid positions; no two turtles will be located at the same grid position; turtle ids are in the range one to ten thousand; the maximum size of the grid in either dimension is sixty; the minimum size is two.
Following the description of the pond and its initial turtle configuration, the remainder of the input, consists of a sequence of K turtle movement requests, one per line. Each movement request consists of a turtle id followed by a movement direction, and indicates that the specified turtle should be requested to move one grid position in the specified direction. The turtle id and movement direction are separated by one or more spaces. The movement direction is one of: `N', `S', `E', `W', `NE', `NW', `SE', `SW'. The turtle requests should be processed sequentially starting from the initial pond configuration given in the input.
The output is a graphical representation of the pond configuration for each data set after all turtle movement requests have been processed. A picture of the pond is rendered using ASCII characters. Beginning with the most northerly row, each row of the grid is represented by a single line in the output. Grid positions along a row are represented by character positions in the output line. The final position of a turtle is marked with an asterisk (`*'); space characters are used to fill empty grid positions. If the output is displayed as text on a computer screen or printed page, the result is a map of turtle positions in the pond, with north toward the top, east toward the right, and west toward the left. Spaces should be generated only when required for positioning turtles; output lines should not have trailing spaces. Print a blank line after each data set.

Sample Input

4 4 3 4
1 0 0
2 0 2
3 3 3
1 S
2 W
2 W
1 SE
4 4 3 4
1 0 0
2 0 2
3 3 3
2 W
2 W
1 S
1 SW

Sample Output

*

 *
   *

 *
*

   *

出處: http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1097

這一題基本上就是照著題目做就對了,不過要注意移動烏龜的時候不能超出池塘的範圍或是撞到別的烏龜(也就是兩個烏龜不能在同一個位置),如果有以上違反規定的移動出現就要忽略。

以下是c++程式碼:

#include <iostream>
#include <map>
using namespace std;

typedef map<int, int> colMap;
struct position {
    int x, y;
};

int main() {
    int row, col, turNum, req;

    while (cin >> row >> col >> turNum >> req) {
        map<int, struct position> findTur;
        map<int, colMap> pool;
        map<int, int> rowMax;
        struct position pos[turNum];

        for (int i=0; i<turNum; i++) {
            int turId, x, y;

            cin >> turId >> x >> y;
            pos[i].x = x;
            pos[i].y = y;
            findTur[turId] = pos[i];
            pool[x][y] = turId;
        }
        for (int i=0; i<req; i++) {
            int turId, x, y;
            string dir;

            cin >> turId >> dir;
            x = findTur[turId].x;
            y = findTur[turId].y;
            pool[x][y] = 0;
            if (dir == "N")
                x--;
            else if (dir == "S")
                x++;
            else if (dir == "E")
                y++;
            else if (dir == "W")
                y--;
            else if (dir == "NE") {
                x--;
                y++;
            }
            else if (dir == "NW") {
                x--;
                y--;
            }
            else if (dir == "SE") {
                x++;
                y++;
            }
            else if (dir == "SW") {
                x++;
                y--;
            }
            if (x >= 0 && y >= 0 && x < row && y < col && pool[x][y] == 0) {
                findTur[turId].x = x;
                findTur[turId].y = y;
                pool[x][y] = turId;
            }
            else
                pool[findTur[turId].x][findTur[turId].y] = turId;
        }
        for (int i=0; i<row; i++) {
            int j;

            for (j=col-1; j>=0 && pool[i][j]==0; j--);
            rowMax[i] = j;
        }
        for (int i=0; i<row; i++) {
            for (int j=0; j<=rowMax[i]; j++) {
                if (pool[i][j])
                    cout << '*';
                else
                    cout << ' ';
            }
            cout << endl;
        }
        cout << endl;
    }

    return 0;
}

10101 - Bangla Numbers


Bangla numbers normally use 'kuti' (10000000), 'lakh' (100000), 'hajar' (1000), 'shata' (100) while expanding and converting to text. You are going to write a program to convert a given number to text with them.

Input
The input file may contain several test cases. Each case will contain a non-negative number <= 999999999999999.

Output
For each case of input, you have to output a line starting with the case number with four digits adjustment followed by the converted text.

Sample Input

23764
45897458973958

Sample Output

   1. 23 hajar 7 shata 64
   2. 45 lakh 89 hajar 7 shata 45 kuti 89 lakh 73 hajar 9 shata 58




出處: http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=13&page=show_problem&problem=1042


這題就是把數字代進去遞迴求解即可。比較需要注意的是input數字可能會很大,所以我使用long long 資料型態,以及要考慮到input是0的情況,最後注意到output開頭的case數字格式是有特別規範的,需要4個格子並且靠右輸出。

以下是c++程式碼:

#include <iostream>
#include <iomanip>
using namespace std;

void bangla(long long num) {
    if (num >= 10000000) {
        bangla(num / 10000000);
        cout << " kuti";
        num %= 10000000;
    }
    if (num >= 100000) {
        bangla(num / 100000);
        cout << " lakh";
        num %= 100000;
    }
    if (num >= 1000) {
        bangla(num / 1000);
        cout << " hajar";
        num %= 1000;
    }
    if (num >= 100) {
        bangla(num / 100);
        cout << " shata";
        num %= 100;
    }
    if (num)
        cout << " " << num;
}

int main() {
    long long num;
    long long countCase = 0;

    while (cin >> num) {
        cout << setw(4) << right << ++countCase << ".";
        if (num)
            bangla(num);
        else
            cout << " 0";
        cout << endl;
    }

    return 0;
}