2013年9月2日 星期一

104 - Arbitrage

Background

The use of computers in the finance industry has been marked with controversy lately as programmed trading -- designed to take advantage of extremely small fluctuations in prices -- has been outlawed at many Wall Street firms. The ethics of computer programming is a fledgling field with many thorny issues.

The Problem

Arbitrage is the trading of one currency for another with the hopes of taking advantage of small differences in conversion rates among several currencies in order to achieve a profit. For example, if $1.00 in U.S. currency buys 0.7 British pounds currency, £1 in British currency buys 9.5 French francs, and 1 French franc buys 0.16 in U.S. dollars, then an arbitrage trader can start with $1.00 and earntex2html_wrap_inline29 dollars thus earning a profit of 6.4 percent.
You will write a program that determines whether a sequence of currency exchanges can yield a profit as described above.
To result in successful arbitrage, a sequence of exchanges must begin and end with the same currency, but any starting currency may be considered.

The Input

The input file consists of one or more conversion tables. You must solve the arbitrage problem for each of the tables in the input file.
Each table is preceded by an integer n on a line by itself giving the dimensions of the table. The maximum dimension is 20; the minimum dimension is 2.
The table then follows in row major order but with the diagonal elements of the table missing (these are assumed to have value 1.0). Thus the first row of the table represents the conversion rates between country 1 and n-1 other countries, i.e., the amount of currency of country i ( tex2html_wrap_inline37 ) that can be purchased with one unit of the currency of country 1.
Thus each table consists of n+1 lines in the input file: 1 line containing n and n lines representing the conversion table.

The Output

For each table in the input file you must determine whether a sequence of exchanges exists that results in a profit of more than 1 percent (0.01). If a sequence exists you must print the sequence of exchanges that results in a profit. If there is more than one sequence that results in a profit of more than 1 percent you must print a sequence of minimal length, i.e., one of the sequences that uses the fewest exchanges of currencies to yield a profit.

Because the IRS (United States Internal Revenue Service) notices lengthy transaction sequences, all profiting sequences must consist of n or fewer transactions where n is the dimension of the table giving conversion rates. The sequence 1 2 1 represents two conversions.
If a profiting sequence exists you must print the sequence of exchanges that results in a profit. The sequence is printed as a sequence of integers with the integer i representing the tex2html_wrap_inline51 line of the conversion table (country i). The first integer in the sequence is the country from which the profiting sequence starts. This integer also ends the sequence.
If no profiting sequence of n or fewer transactions exists, then the line
no arbitrage sequence exists
should be printed.

Sample Input


3
1.2 .89
.88 5.1
1.1 0.15
4
3.1    0.0023    0.35
0.21   0.00353   8.13 
200    180.559   10.339
2.11   0.089     0.06111
2
2.0
0.45

Sample Output


1 2 1
1 2 4 1
no arbitrage sequence exists

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


問題敘述

此問題首先會輸入國家的數量,並且輸入每個國家和每個國家的匯率兌換表(同個國家的兌換匯率不會輸入,因為一定是1),要您求出可以經由最少的兌換次數來達到獲利超過1%的兌換方式(可以在任何國家的幣紙上獲利),若有兩種以上最少兌換次數可以獲利超過1%,隨便印出一種兌換方法即可,若找不到兌換方法,則印出"no arbitrage sequence exists"。

解題思路

此題使用Dynamic programming來解,首先求出各個國家只兌換1次可以得到的最佳解(也就是初始的匯率兌換表),再利用只兌換1次的最佳解求出只兌換2次的最佳解,接著再利用只兌換2次的最佳解求出只兌換3次的最佳解...依此類推,一直求到有國家自己兌換自己可以超過1.01就表示找到解了,若一直求到n次兌換都找不到解,表示此解找不到。

c++ 程式碼

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

void findPath(vector< vector< vector<int> > >& path, int startCountry, int endCountry, int step) {
    if (path[step][startCountry][endCountry] != -1) {
        findPath(path, startCountry, path[step][startCountry][endCountry], step - 1);
        cout << " " << path[step][startCountry][endCountry] + 1;
    }
}

int main() {
    int countryNum;

    while (cin >> countryNum) {
         vector< vector< vector<double> > > bestRateEachStep(countryNum, vector< vector<double> >(countryNum,
                      vector<double>(countryNum, 0)));
         vector< vector< vector<int> > > path(countryNum, vector< vector<int> >(countryNum,
                      vector<int>(countryNum, -1)));
         int startCountry = -1;
         int lastStep = -1;

        for (int i=0; i<countryNum; i++) {
            for (int j=0; j<countryNum; j++) {
                if (i == j)
                    bestRateEachStep[0][i][j] = 1;
                else
                    cin >> bestRateEachStep[0][i][j];
            }
        }
        for (int step=1; step<countryNum; step++) {
            for (int k=0; k<countryNum; k++) {
                for (int i=0; i<countryNum; i++) {
                    for (int j=0; j<countryNum; j++) {
                        if (bestRateEachStep[step - 1][i][k] * bestRateEachStep[0][k][j] > bestRateEachStep[step][i][j]) {
                            bestRateEachStep[step][i][j] = bestRateEachStep[step - 1][i][k] * bestRateEachStep[0][k][j];
                            path[step][i][j] = k;
                        }
                    }
                }
            }
            for (int i=0; i<countryNum; i++) {
                if (bestRateEachStep[step][i][i] > 1.01) {
                    startCountry = i;
                    lastStep = step;
                    break;
                }
            }
            if (startCountry != -1)
                break;
        }
        if (startCountry == -1)
            cout << "no arbitrage sequence exists\n";
        else {
            cout << startCountry + 1;
            findPath(path, startCountry, startCountry, lastStep);
            cout << " " << startCountry + 1 << endl;
        }
    }

    return 0;
}

2013年8月31日 星期六

103 - Stacking Boxes


Background

Some concepts in Mathematics and Computer Science are simple in one or two dimensions but become more complex when extended to arbitrary dimensions. Consider solving differential equations in several dimensions and analyzing the topology of an n-dimensional hypercube. The former is much more complicated than its one dimensional relative while the latter bears a remarkable resemblance to its ``lower-class'' cousin.

The Problem

Consider an n-dimensional ``box'' given by its dimensions. In two dimensions the box (2,3) might represent a box with length 2 units and width 3 units. In three dimensions the box (4,8,9) can represent a box tex2html_wrap_inline40 (length, width, and height). In 6 dimensions it is, perhaps, unclear what the box (4,5,6,7,8,9) represents; but we can analyze properties of the box such as the sum of its dimensions.
In this problem you will analyze a property of a group of n-dimensional boxes. You are to determine the longest nesting string of boxes, that is a sequence of boxes tex2html_wrap_inline44 such that each box tex2html_wrap_inline46 nests in box tex2html_wrap_inline48 ( tex2html_wrap_inline50 .
A box D = ( tex2html_wrap_inline52 ) nests in a box E = ( tex2html_wrap_inline54 ) if there is some rearrangement of the tex2html_wrap_inline56 such that when rearranged each dimension is less than the corresponding dimension in box E. This loosely corresponds to turning box D to see if it will fit in box E. However, since any rearrangement suffices, box D can be contorted, not just turned (see examples below).
For example, the box D = (2,6) nests in the box E = (7,3) since D can be rearranged as (6,2) so that each dimension is less than the corresponding dimension in E. The box D = (9,5,7,3) does NOT nest in the box E = (2,10,6,8) since no rearrangement of D results in a box that satisfies the nesting property, but F = (9,5,7,1) does nest in box E since F can be rearranged as (1,9,5,7) which nests in E.
Formally, we define nesting as follows: box D = ( tex2html_wrap_inline52 ) nests in box E = ( tex2html_wrap_inline54 ) if there is a permutation tex2html_wrap_inline62 of tex2html_wrap_inline64such that ( tex2html_wrap_inline66 ) ``fits'' in ( tex2html_wrap_inline54 ) i.e., if tex2html_wrap_inline70 for all tex2html_wrap_inline72 .

The Input

The input consists of a series of box sequences. Each box sequence begins with a line consisting of the the number of boxes k in the sequence followed by the dimensionality of the boxes, n (on the same line.)
This line is followed by k lines, one line per box with the n measurements of each box on one line separated by one or more spaces. The tex2html_wrap_inline82 line in the sequence ( tex2html_wrap_inline84 ) gives the measurements for the tex2html_wrap_inline82 box.
There may be several box sequences in the input file. Your program should process all of them and determine, for each sequence, which of the kboxes determine the longest nesting string and the length of that nesting string (the number of boxes in the string).
In this problem the maximum dimensionality is 10 and the minimum dimensionality is 1. The maximum number of boxes in a sequence is 30.

The Output

For each box sequence in the input file, output the length of the longest nesting string on one line followed on the next line by a list of the boxes that comprise this string in order. The ``smallest'' or ``innermost'' box of the nesting string should be listed first, the next box (if there is one) should be listed second, etc.
The boxes should be numbered according to the order in which they appeared in the input file (first box is box 1, etc.).
If there is more than one longest nesting string then any one of them can be output.

Sample Input


5 2
3 7
8 10
5 2
9 11
21 18
8 6
5 2 20 1 30 10
23 15 7 9 11 3
40 50 34 24 14 4
9 10 11 12 13 14
31 4 18 8 27 17
44 32 13 19 41 19
1 2 3 4 5 6
80 37 47 18 21 9

Sample Output


5
3 1 2 4 5
4
7 2 5 6


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


問題描述

此問題首先會給您盒子的數量,並且告訴您盒子的維度(會超過三維),接著會輸入每一個盒子的邊長,最後要您求出最多可以疊多少個盒子,並且印出疊最多盒子的串列。

解題思路

首先如何判斷盒子A是否可以塞進盒子B裡呢? 根據題目的定義,只要盒子A有任何一種邊長的排列方式可以使得盒子A所有的邊長都比盒子B的邊長來得小,就可以將盒子A塞進盒子B裡。最直接的判斷方法就是把所有盒子的邊長都先排序好,最後只需要從第一個邊長逐一比較到最後一個邊長,若盒子A的每個邊長皆比盒子B來得小,那就表示盒子A可以塞進盒子B裡,否則就不行。至於如何找出可以疊最多盒子的串列呢? 其實此問題可以用dynamic programming的方法來解,也就是使用類floyd-warshall的演算法,把每個盒子視為一個點,把可以疊的盒子數量視為路徑長,最後只需把求最短路徑改成求最長路徑即可。

c++程式碼

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

void findPath(vector< vector<int> >& path, int startVertex, int endVertex) {
    if (path[startVertex][endVertex] != -1) {
        findPath(path, startVertex, path[startVertex][endVertex]);
        cout << " " << path[startVertex][endVertex] + 1;
        findPath(path, path[startVertex][endVertex], endVertex);
    }
}

int main() {
    int boxNum, dimens;

    while (cin >> boxNum >> dimens) {
        vector< vector<int> > boxes(boxNum, vector<int>(dimens, 0));
        vector< vector<int> > pathLength(boxNum, vector<int>(boxNum, 0));
        vector< vector<int> > path(boxNum, vector<int>(boxNum, -1));
        int maxPathLength = -1;
        int startVertex = -1;
        int endVertex = -1;

        for (int i=0; i<boxes.size(); i++) {
            for (int j=0; j<boxes[i].size(); j++)
                cin >> boxes[i][j];
            sort(boxes[i].begin(), boxes[i].end());
        }
        for (int i=0; i<boxes.size(); i++) {
            for (int j=0; j<boxes.size(); j++) {
                bool isNest = true;

                for (int k=0; k<boxes[i].size(); k++) {
                    if (boxes[i][k] >= boxes[j][k]) {
                        isNest = false;
                        break;
                    }
                }
                if (isNest)
                    pathLength[i][j] = 1;
                if (pathLength[i][j] > maxPathLength) {
                    maxPathLength = pathLength[i][j];
                    startVertex = i;
                    endVertex = j;
                }
            }
        }
        for (int k=0; k<boxes.size(); k++) {
            for (int i=0; i<boxes.size(); i++) {
                for (int j=0; j<boxes.size(); j++) {
                    if (pathLength[i][k] != 0 && pathLength[k][j] != 0 && pathLength[i][k] + pathLength[k][j] > pathLength[i][j]) {
                        pathLength[i][j] = pathLength[i][k] + pathLength[k][j];
                        path[i][j] = k;
                        if (pathLength[i][j] > maxPathLength) {
                            maxPathLength = pathLength[i][j];
                            startVertex = i;
                            endVertex = j;
                        }
                    }
                }
            }
        }
        cout << maxPathLength + 1 << endl;
        cout << startVertex + 1;
        if (maxPathLength) {
            findPath(path, startVertex, endVertex);
            cout << " " << endVertex + 1 << endl;
        }
        else
            cout << endl;
    }

    return 0;
}

2013年8月23日 星期五

10940 - Throwing cards away II

Given is an ordered deck of n cards numbered 1 to n with card 1 at the top and card n at the bottom. The following operation is performed as long as there are at least two cards in the deck:
Throw away the top card and move the card that is now on the top of the deck to the bottom of the deck.
Your task is to find the last, remaining card.
Each line of input (except the last) contains a positive number n ≤ 500000. The last line contains 0 and this line should not be processed. For each number from input produce one line of output giving the last remaining card. Input will not contain more than 500000 lines.

Sample input

7
19
10
6
0

Output for sample input

6
6
4
4

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



此題的操作具有遞迴關係。首先2張牌的情況,經過題目所說的操作答案就是第2張牌,至於3張牌的情況,經過題目所說的操作之後會變成2張牌的情況,4張牌的情況經過操作之後會變成3張牌的情況 ... n張牌的情況經過操作會變成n - 1張牌的情況。所以每個情況的解都可以由前一個情況來推算,利用dynamic programming的觀念,先把2到500000張牌的每個情況都推算出來並且記起來,接下來就看題目要的是哪個情況就把哪個情況的解叫出來就好了。至於如何從n - 1張牌情況的解推出n張牌情況的解呢?若n - 1張牌情況的解是最後一張,則n張牌情況的解就是第2張,若n - 1張情況的解不是最後一張,那這個解的位置加上2就是n張牌情況的解。此題還有一點要注意的是若輸入是1則輸出就是1,因為無法進行任何操作。

c++ code:

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

int main() {
    map<int, int> table;

    table[1] = 1;
    table[2] = 2;
    for (int i=3; i<=500000; i++) {
        if (table[i - 1] == i - 1)
            table[i] = 2;
        else
            table[i] = table[i - 1] + 2;
    }
    while (true) {
        int n;

        cin >> n;
        if (!n)
            break;
        cout << table[n] << endl;
    }

    return 0;
}

2013年8月18日 星期日

913 - Joana and the Odd Numbers

Joana loves playing with odd numbers. In the other day, she started writing, in each line, an odd number of odd numbers. It looked as follows:
 1
 3  5  7
 9 11 13 15 17
19 21 23 25 27 29 31
...
On a certain line Joana wrote 55 odd numbers. Can you discover the sum of the last three numbers written in that line? Can you do this more generally for a given quantity of odd numbers?

Problem

Given the number N of odd numbers in a certain line, your task is to determine the sum of the last three numbers of that line.

Input

The input is a sequence of lines, one odd number N (1<N<1000000000) per line

Output

For each input line write the sum of the last three odd numbers written by Joana in that line with N numbers. This sum is guaranteed to be less than 263.

Sample Input

3
5
7

Sample Output


15
45
87

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



這一題題目是給您其中某一列奇數的數目,接著要您求出這一列最後三個奇數的總和。如果這一題用暴力解法應該會超過time limit,因為測試資料的範圍是1<N<1000000000,所以此題不能用暴力解。可以先思考一下題目要您求出的答案是"某一奇數列的最後三個數字的總和",所以其實只要知道這三個數字的其中一個數字就好了,因為其他兩個數字可以推淂。既然如此我們可以選擇先求最後一個數字,因為最後一個數字比較好從規律推到,可以觀察一下題目的規律來推出最後一個數字:

若輸入為3, 最後一個數字為:

1 + 3 * 2 = 7

則三數總和為:

3 + 5 + 7 = 15

若輸入為5, 最後一個數字為:

1 + 3 * 2 + 5 * 2 = 17

則三數總和為:

17 + 15 + 13 = 45
.
.
.
若輸入為n, 最後一個數字為:

1 + 3 * 2 + 5 * 2  + ... + n * 2 = a

則三數總和為:

a + a - 2 + a - 4 = 3 * a - 6

至於1 + 3 * 2 + 5 * 2  + ... + n * 2 = a這個算式可以簡化成以下式子:

1 + 2 * (3 + 5 + ... + n) = a

而括弧裡面的式子就是等差級數,所以利用等差級數公式代掉後變成以下算式:

1 + 2 * (3 + n) * (n - 1) / 2 / 2

整理一下可以變成此式:

(n ^ 2 + 2 * n - 1) / 2 = a

最後再把a代入3 * a - 6就變成以下式子:

3 * (n ^ 2 + 2 * n - 1) / 2 - 6

接著可以簡化成

3 * (n ^ 2 + 2 * n - 5) / 2

這就是最終公式,把input代入即可求解。還有一個要注意的是若資料型態用int會容納不下最終解,所以必須要用更大的資料型態來儲存。

以下是c++ code:

#include <iostream>
using namespace std;

int main() {
    long long n;

    while (cin >> n)
        cout << 3 * (n * n + 2 * n - 5) / 2  << endl;

    return 0;
}

591 - Box of Bricks

Little Bob likes playing with his box of bricks. He puts the bricks one upon another and builds stacks of different height. ``Look, I've built a wall!'', he tells his older sister Alice. ``Nah, you should make all stacks the same height. Then you would have a real wall.'', she retorts. After a little con- sideration, Bob sees that she is right. So he sets out to rearrange the bricks, one by one, such that all stacks are the same height afterwards. But since Bob is lazy he wants to do this with the minimum number of bricks moved. Can you help?


Input 

The input consists of several data sets. Each set begins with a line containing the number n of stacks Bob has built. The next line contains nnumbers, the heights hi of the n stacks. You may assume $1 Ÿ\le n \leŸ 50$ and $1 \leŸ h_i Ÿ\le 100$.
The total number of bricks will be divisible by the number of stacks. Thus, it is always possible to rearrange the bricks such that all stacks have the same height.
The input is terminated by a set starting with n = 0. This set should not be processed.

Output 

For each set, first print the number of the set, as shown in the sample output. Then print the line ``The minimum number of moves is k.'', wherek is the minimum number of bricks that have to be moved in order to make all the stacks the same height.
Output a blank line after each set.

Sample Input 

6
5 2 4 1 7 5
0

Sample Output 

Set #1
The minimum number of moves is 5.

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



題目要求您要用最少的移動次數移動積木,來把每一堆積木都變得一樣高,題目假設總積木數除以積木堆數都有辦法整除,也就是說積木經過移動後都有辦法變得一樣高。既然要用最少的次數移動,那每一次移動就要把最高的積木堆拿一個積木下來填補到最低的積木堆,一直到每個積木堆都一樣高為止。

c++ code:

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

int main() {
    int setCount = 0;

    while (true) {
        int n;
        vector<int> heights;
        int moveCount = 0;

        cin >> n;
        if (n == 0)
            break;
        setCount++;
        for (int i=0; i<n; i++) {
            int h;

            cin >> h;
            heights.push_back(h);
        }
        while (true) {
            int max = heights[0];
            int min = heights[0];
            int maxIndex = 0;
            int minIndex = 0;

            for (int i=1; i<heights.size(); i++) {
                if (heights[i] > max) {
                    max = heights[i];
                    maxIndex = i;
                }
                else if (heights[i] < min) {
                    min = heights[i];
                    minIndex = i;
                }
            }
            if (max == min)
                break;
            moveCount++;
            heights[maxIndex]--;
            heights[minIndex]++;
        }
        cout << "Set #" << setCount << endl;
        cout << "The minimum number of moves is " << moveCount << ".\n\n";
    }

    return 0;
}

2013年8月17日 星期六

579 - ClockHands

The medieval interest in mechanical contrivances is well illustrated by the development of the mechanical clock, the oldest of which is driven by weights and controlled by a verge, an oscillating arm engaging with a gear wheel. It dates back to 1386.
Clocks driven by springs had appeared by the mid-15th century, making it possible to con- struct more compact mechanisms and preparing the way for the portable clock.
English spring-driven pendulum clocks were first commonly kept on a small wall bracket and later on a shelf. Many bracket clocks contained a drawer to hold the winding key. The earliest bracket clocks, made for a period after 1660, were of architectural design, with pillars at the sides and a pediment on top.
In 17th- and 18th-century France, the table clock became an object of monumental design, the best examples of which are minor works of sculpture.
The longcase clocks (also called grandfather clocks) are tall pendulum clock enclosed in a wooden case that stands upon the floor and is typically from 6 to 7.5 feet (1.8 to 2.3 m) in height. Later, the name ``grandfather clock'' became popular after the popular song "My Grandfather's Clock," written in 1876 by Henry Clay Work.


One of the first atomic clocks was an ammonia-controlled clock. It was built in 1949 at the National Bureau of Standards, Washington, D.C.; in this clock the frequency did not vary by more than one part in 108
Nuclear clocks are built using two clocks. The aggregate of atoms that emit the gamma radiation of precise frequency may be called the emitter clock; the group of atoms that absorb this radiation is the absorber clock. One pair of these nuclear clocks can detect energy changes of one part in 1014 , being about 1,000 times more sensitive than the best atomic clock.
The cesium clock is the most accurate type of clock yet developed. This device makes use of transitions between the spin states of the cesium nucleus and produces a frequency which is so regular that it has been adopted for establishing the time standard.


The history of clocks is fascinating, but unrelated to this problem. In this problem, you are asked to find the angle between the minute hand and the hour hand on a regular analog clock. Assume that the second hand, if there were one, would be pointing straight up at the 12. Give all angles as the smallest positive angles. For example 9:00 is 90 degrees; not -90 or 270 degrees.

Input 

The input is a list of times in the form H:M, each on their own line, with $1 \le H \le 12$ and $00 \le M \le 59$. The input is terminated with the time 0:00. Note that H may be represented with 1 or 2 digits (for 1-9 or 10-12, respectively); M is always represented with 2 digits (The input times are what you typically see on a digital clock).

Output 

The output displays the smallest positive angle in degrees between the hands for each time. The answer should between 0 degrees and 180degrees for all input times. Display each angle on a line by itself in the same order as the input. The output should be rounded to the nearest 1/1000, i.e., three places after the decimal point should be printed.

Sample Input 

12:00
9:00
8:10
0:00

Sample Output 

0.000
90.000
175.000

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



這題是計算時針和分針之間夾角的角度(0<=角度<=180),我計算的方式是先算出時針與12點的夾角再扣掉分針與12點的夾角再加上時針隨著分針移動的角度取絕對值,最後再判斷這個角度是否大於180,若大於180則用360去扣掉此角度算出比較小的夾角,若沒有則本身就是比較小的夾角。

c++ code:

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

int main() {
    string time;

    while (true) {
        int hour = 0;
        int min = 0;
        int i;
        double angle;

        cin >> time;
        if (time == "0:00")
            break;
        for (i=0; time[i]!=':'; i++)
            hour = hour * 10 + time[i] - '0';
        for (i=i+1; i<time.length(); i++)
            min = min * 10 + time[i] - '0';
        angle = abs(hour * 5 * 6 - min * 6 + min / 2.);
        if (angle > 180)
            cout << setprecision(3) << fixed << (360 - angle) << endl;
        else
            cout << setprecision(3) << fixed << angle << endl;
    }

    return 0;
}

494 - Kindergarten Counting Game

Everybody sit down in a circle. Ok. Listen to me carefully.
``Woooooo, you scwewy wabbit!''
Now, could someone tell me how many words I just said?

Input and Output

Input to your program will consist of a series of lines, each line containing multiple words (at least one). A ``word'' is defined as a consecutive sequence of letters (upper and/or lower case).

Your program should output a word count for each line of input. Each word count should be printed on a separate line.

Sample Input


Meep Meep!
I tot I taw a putty tat.
I did! I did! I did taw a putty tat.
Shsssssssssh ... I am hunting wabbits. Heh Heh Heh Heh ...

Sample Output


2
7
10
9

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



這題是要求您去數有幾個英文單字,這邊一個單字的定義是連續的大寫或小寫英文字母就算一個單字,所以只要搭配布林變數就可以解決此題。當遇到第一個英文字母的時候將布林設定為true並且單字數加一,當遇到不是英文字母的時候就將布林改為false,依此類推就可以數出有幾個英文單字。

c++ code:

#include <iostream>
using namespace std;

int main() {
    string line;

    while (getline(cin, line)) {
        bool flag = false;
        int count = 0;

        for (int i=0; i<line.length(); i++) {
            if ((line[i] >= 'A' && line[i] <= 'Z') || (line[i] >= 'a' && line[i] <= 'z')) {
                if (!flag) {
                    count++;
                    flag = true;
                }
            }
            else
                flag = false;
        }
        cout << count << endl;
    }

    return 0;
}

2013年8月16日 星期五

488 - Triangle Wave

In this problem you are to generate a triangular wave form according to a specified pair of Amplitude and Frequency.

Input and Output

The input begins with a single positive integer on a line by itself indicating the number of the cases following, each of them as described below. This line is followed by a blank line, and there is also a blank line between two consecutive inputs.
Each input set will contain two integers, each on a separate line. The first integer is the Amplitude; the second integer is the Frequency.
For each test case, the output must follow the description below. The outputs of two consecutive cases will be separated by a blank line.
For the output of your program, you will be printing wave forms each separated by a blank line. The total number of wave forms equals the Frequency, and the horizontal ``height'' of each wave equals the Amplitude. The Amplitude will never be greater than nine.
The waveform itself should be filled with integers on each line which indicate the ``height'' of that line.
NOTE: There is a blank line after each separate waveform, excluding the last one.

Sample Input


1

3
2

Sample Output


1
22
333
22
1

1
22
333
22
1
 

出處: UVa Online Judge - Triangle Wave


問題敘述

題目會先輸入共有幾組測試資料,接著輸入每組測試資料的內容。各組測試資料有兩個整數,第一個整數是振幅,第二個整數是頻率,此題要求您依照振幅和頻率印出波形。

解題思路

沒有什麼思路,只要印出和振幅一樣高的波並且重複印出題目給的頻率次即可。

c++ 程式碼

#include <iostream>
using namespace std;

int main() {
    int n;
    bool isFirst = true;

    cin >> n;
    for (int i=0; i<n; i++) {
        int amp, fre;

        cin.get();
        cin >> amp >> fre;
        for (int j=0; j<fre; j++) {
            bool reverse = false;

            if (isFirst)
                isFirst = false;
            else
                cout << endl;
            for (int k=1; k>=1; (reverse)? k--:k++) {
                for (int m=1; m<=k; m++)
                    cout << k;
                cout << endl;
                if (k == amp)
                    reverse = true;
            }
        }
    }

    return 0;
}

2013年8月12日 星期一

477 - Points in Figures: Rectangles and Circles

Given a list of figures (rectangles and circles) and a list of points in the x-y plane, determine for each point which figures (if any) contain the point.

Input

There will be ntex2html_wrap_inline232 ) figures descriptions, one per line. The first character will designate the type of figure (``r'', ``c'' for rectangle or circle, respectively). This character will be followed by values which describe that figure.
  • For a rectangle, there will be four real values designating the x-y coordinates of the upper left and lower right corners.
  • For a circle, there will be three real values, designating the x-y coordinates of the center and the radius.
The end of the list will be signalled by a line containing an asterisk in column one.

The remaining lines will contain the x-y coordinates, one per line, of the points to be tested. The end of this list will be indicated by a point with coordinates 9999.9 9999.9; these values should not be included in the output.
Points coinciding with a figure border are not considered inside.

Output

For each point to be tested, write a message of the form:
Point i is contained in figure j
for each figure that contains that point. If the point is not contained in any figure, write a message of the form:
Point i is not contained in any figure
Points and figures should be numbered in the order in which they appear in the input.

Sample Input


r 8.5 17.0 25.5 -8.5
c 20.2 7.3 5.8
r 0.0 10.3 5.5 0.0
c -5.0 -5.0 3.7
r 2.5 12.5 12.5 2.5
c 5.0 15.0 7.2
*
2.0 2.0
4.7 5.3
6.9 11.2
20.0 20.0
17.6 3.2
-5.2 -7.8
9999.9 9999.9

Sample Output


Point 1 is contained in figure 3
Point 2 is contained in figure 3
Point 2 is contained in figure 5
Point 3 is contained in figure 5
Point 3 is contained in figure 6
Point 4 is not contained in any figure
Point 5 is contained in figure 1
Point 5 is contained in figure 2
Point 6 is contained in figure 4

Diagrama of sample input figures and data points

出處: UVa Online Judge - Points in Figures: Rectangles and Circles


問題敘述

這題是 476 - Points in Figures: Rectangles (Chinese version) 這一題的擴充,一樣是判斷點有沒有在圖形內,只不過多增加了圓形。

解題思路

如何判斷點有沒有在矩形內在上一題就已經說明過,所以不再贅述。至於如何判斷點有沒有在圓形內就是算出點和圓心之間的距離並且判斷此距離有沒有小於半徑即可。為了操作方便,程式裡用了點繼承的小技巧,來達到一樣是Figure但是長方形和圓形各有不同判斷點是否在圖形內的方法的效果。

c++ 程式碼

#include <iostream>
#include <vector>
#include <cmath>
using namespace std;

class Point {
    public:
        double x, y;
        Point(double, double);
};

Point::Point(double x, double y):x(x), y(y) {
}

class Figure {
    public:
        virtual bool contain(Point*) = 0;
};

class Rectangle: public Figure {
    public:
        double x1, y1, x2, y2;
        Rectangle(double, double, double, double);
        bool contain(Point*);
};

Rectangle::Rectangle(double x1, double y1, double x2, double y2):x1(x1), y1(y1), x2(x2), y2(y2) {
}

bool Rectangle::contain(Point* point) {
    if (this->x1 < point->x && point->x < this->x2 && this->y1 > point->y && point->y > this->y2)
        return true;
    else
        return false;
}

class Circle: public Figure {
    public:
        double x, y, radius;
        Circle(double, double, double);
        bool contain(Point*);
};

Circle::Circle(double x, double y, double radius):x(x), y(y), radius(radius) {
}

bool Circle::contain(Point* point) {
    double dis = sqrt(pow(this->x - point->x, 2) + pow(this->y - point->y, 2));

    if (dis < radius)
        return true;
    else
        return false;
}

int main() {
    vector<Figure*> figVec;
    vector<Point*> pointVec;

    while (true) {
        char sym;

        cin >> sym;
        if (sym == '*')
            break;
        else if (sym == 'r') {
            double x1, y1, x2, y2;
            Rectangle* rec;

            cin >> x1 >> y1 >> x2 >> y2;
            rec = new Rectangle(x1, y1, x2, y2);
            figVec.push_back(rec);
        }
        else {
            double x, y, radius;
            Circle* circle;

            cin >> x >> y >> radius;
            circle = new Circle(x, y, radius);
            figVec.push_back(circle);
        }
    }
    while (true) {
        double x, y;
        Point* point;

        cin >> x >> y;
        if (x == 9999.9 && y == 9999.9)
            break;
        point = new Point(x, y);
        pointVec.push_back(point);
    }
    for (int i=0; i<pointVec.size(); i++) {
        bool isContained = false;

        for (int j=0; j<figVec.size(); j++) {
            if (figVec[j]->contain(pointVec[i])) {
                cout << "Point " << i + 1 << " is contained in figure " << j + 1 << endl;
                isContained = true;
            }
        }
        if (!isContained)
            cout << "Point " << i + 1 << " is not contained in any figure" << endl;
    }
    for (int i=0; i<figVec.size(); i++)
        delete figVec[i];
    for (int i=0; i<pointVec.size(); i++)
        delete pointVec[i];

    return 0;
}

476 - Points in Figures: Rectangles

Given a list of rectangles and a list of points in the x-y plane, determine for each point which figures (if any) contain the point.

Input

There will be ntex2html_wrap_inline220 ) rectangles descriptions, one per line. The first character will designate the type of figure (``r'' for rectangle). This character will be followed by four real values designating the x-y coordinates of the upper left and lower right corners.
The end of the list will be signalled by a line containing an asterisk in column one.

The remaining lines will contain the x-y coordinates, one per line, of the points to be tested. The end of this list will be indicated by a point with coordinates 9999.9 9999.9; these values should not be included in the output.
Points coinciding with a figure border are not considered inside.

Output

For each point to be tested, write a message of the form:
Point i is contained in figure j
for each figure that contains that point. If the point is not contained in any figure, write a message of the form:
Point i is not contained in any figure
Points and figures should be numbered in the order in which they appear in the input.

Sample Input


r 8.5 17.0 25.5 -8.5
r 0.0 10.3 5.5 0.0
r 2.5 12.5 12.5 2.5
*
2.0 2.0
4.7 5.3
6.9 11.2
20.0 20.0
17.6 3.2
-5.2 -7.8
9999.9 9999.9

Sample Output


Point 1 is contained in figure 2
Point 2 is contained in figure 2
Point 2 is contained in figure 3
Point 3 is contained in figure 3
Point 4 is not contained in any figure
Point 5 is contained in figure 1
Point 6 is not contained in any figure

Diagrama of sample input figures and data points

出處: UVa Online Judge - Points in Figures: Rectangles


問題敘述

此題會先輸入很多行長方形座標資料,每行的開頭為 r 代表長方形,接著會輸入四個浮點數,前兩個浮點數代表此長方形左上角的座標,後兩個浮點數代表此長方形右下角的座標,長方形資料一直輸入到出現 * 就結束。接著會輸入很多行成對的浮點數,每對各代表一個點座標,您的任務是要求出這些點各被包含在哪些長方形裡面。

解題思路

因為矩形的輸入資料只給出左上角的座標(設: x1, y1)以及右下角的座標(設: x2, y2),所以可以知道 x1 <= x2 和 y1 >= y2。若點(設 x, y)要落在矩形裡勢必要符合此條件: x1 < x < x2 and y1 > y > y2(沒有等於,因為落在邊上不算被包含在裡面),依照此規則就可以判斷點是否落在矩形內。

c++ 程式碼

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

class Figure {
    public:
        double x1, y1, x2, y2;
        Figure(double, double, double, double);
};

Figure::Figure(double x1, double y1, double x2, double y2):x1(x1), y1(y1), x2(x2), y2(y2) {
}

class Point {
    public:
        double x, y;
        Point(double, double);
};

Point::Point(double x, double y):x(x), y(y) {
}

int main() {
    vector<Figure*> figVec;
    vector<Point*> pointVec;

    while (true) {
        char sym;
        double x1, y1, x2, y2;
        Figure* fig;

        cin >> sym;
        if (sym == '*')
            break;
        cin >> x1 >> y1 >> x2 >> y2;
        fig = new Figure(x1, y1, x2, y2);
        figVec.push_back(fig);
    }
    while (true) {
        double x, y;
        Point* point;

        cin >> x >> y;
        if (x == 9999.9 && y == 9999.9)
            break;
        point = new Point(x, y);
        pointVec.push_back(point);
    }
    for (int i=0; i<pointVec.size(); i++) {
        bool isContained = false;

        for (int j=0; j<figVec.size(); j++) {
            if (figVec[j]->x1 < pointVec[i]->x && pointVec[i]->x < figVec[j]->x2 &&
                    figVec[j]->y1 > pointVec[i]->y && pointVec[i]->y > figVec[j]->y2) {
                cout << "Point " << i + 1 << " is contained in figure " << j + 1 << endl;
                isContained = true;
            }
        }
        if (!isContained)
            cout << "Point " << i + 1 << " is not contained in any figure" << endl;
    }
    for (int i=0; i<figVec.size(); i++)
        delete figVec[i];
    for (int i=0; i<pointVec.size(); i++)
        delete pointVec[i];

    return 0;
}

2013年8月10日 星期六

458 - The Decoder

Write a complete program that will correctly decode a set of characters into a valid message. Your program should read a given file of a simple coded set of characters and print the exact message that the characters contain. The code key for this simple coding is a one for one character substitution based upon a single arithmetic manipulation of the printable portion of the ASCII character set.

Input and Output

For example: with the input file that contains:

1JKJ'pz'{ol'{yhklthyr'vm'{ol'Jvu{yvs'Kh{h'Jvywvyh{pvu5
1PIT'pz'h'{yhklthyr'vm'{ol'Pu{lyuh{pvuhs'I|zpulzz'Thjopul'Jvywvyh{pvu5
1KLJ'pz'{ol'{yhklthyr'vm'{ol'Kpnp{hs'Lx|pwtlu{'Jvywvyh{pvu5
your program should print the message:
*CDC is the trademark of the Control Data Corporation.
*IBM is a trademark of the International Business Machine Corporation.
*DEC is the trademark of the Digital Equipment Corporation.
Your program should accept all sets of characters that use the same encoding scheme and should print the actual message of each set of characters.

Sample Input


1JKJ'pz'{ol'{yhklthyr'vm'{ol'Jvu{yvs'Kh{h'Jvywvyh{pvu5
1PIT'pz'h'{yhklthyr'vm'{ol'Pu{lyuh{pvuhs'I|zpulzz'Thjopul'Jvywvyh{pvu5
1KLJ'pz'{ol'{yhklthyr'vm'{ol'Kpnp{hs'Lx|pwtlu{'Jvywvyh{pvu5

Sample Output


*CDC is the trademark of the Control Data Corporation.
*IBM is a trademark of the International Business Machine Corporation.
*DEC is the trademark of the Digital Equipment Corporation.
 

出處: UVa Online Judge - The Decoder




問題敘述

此題會輸入一個亂七八糟的文本,要您把它解碼成看得懂的文本輸出。

解題思路

此題的輸入文本對應輸出文本有非常明顯的規律,輸入每個字元的 ascii code 減去7就是輸出的字元。

c++ 程式碼

#include <iostream>
using namespace std;

int main() {
    string input;

    while (getline(cin, input)) {
        for (int i=0; i<input.length(); i++)
            cout << (char)(input[i] - 7);
        cout << endl;
    }

    return 0;
}

272 - TEX Quotes

TeX is a typesetting language developed by Donald Knuth. It takes source text together with a few typesetting instructions and produces, one hopes, a beautiful document. Beautiful documents use `` and " to delimit quotations, rather than the mundane " which is what is provided by most keyboards. Keyboards typically do not have an oriented double-quote, but they do have a left-single-quote ` and a right-single-quote '. Check your keyboard now to locate the left-single-quote key ` (sometimes called the ``backquote key") and the right-single-quote key ' (sometimes called the ``apostrophe" or just ``quote"). Be careful not to confuse the left-single-quote ` with the ``backslash" key \. TeX lets the user type two left-single-quotes `` to create a left-double-quote `` and two right-single-quotes '' to create a right-double-quote ''. Most typists, however, are accustomed to delimiting their quotations with the un-oriented double-quote ".

If the source contained
"To be or not to be," quoth the bard, "that is the question."
then the typeset document produced by TeX would not contain the desired form:


``To be or not to be," quoth the bard, ``that is the question."

In order to produce the desired form, the source file must contain the sequence:
``To be or not to be,'' quoth the bard, ``that is the question.''

You are to write a program which converts text containing double-quote (") characters into text that is identical except that double-quotes have been replaced by the two-character sequences required by TeX for delimiting quotations with oriented double-quotes. The double-quote (") characters should be replaced appropriately by either `` if the " opens a quotation and by '' if the " closes a quotation. Notice that the question of nested quotations does not arise: The first " must be replaced by ``, the next by '', the next by ``, the next by '', the next by ``, the next by'', and so on.

Input and Output

Input will consist of several lines of text containing an even number of double-quote (") characters. Input is ended with an end-of-file character. The text must be output exactly as it was input except that:

  • the first " in each pair is replaced by two ` characters: `` and
  • the second " in each pair is replaced by two ' characters: ''.

Sample Input


"To be or not to be," quoth the Bard, "that
is the question".
The programming contestant replied: "I must disagree.
To `C' or not to `C', that is The Question!"

Sample Output


``To be or not to be,'' quoth the Bard, ``that
is the question''.
The programming contestant replied: ``I must disagree.
To `C' or not to `C', that is The Question!''
 
出處: UVa Online Judge - TEX Quotes


問題敘述

此題會輸入一個文本,文本中包含空白和換行,要求您把成對的 " 改成 `` 開頭和 '' (兩個單引號) 結尾。

解題思路

沒有什麼思路,就是把第奇數次出現的 " 改成 ``,第偶數次出現的 " 改成 '' (兩個單引號),其他的字元就直接輸出即可。

c++ 程式碼

#include <iostream>
using namespace std;

int main() {
    string temp;
    int num = 0;

    while (getline(cin, temp)) {
        for (int i=0; i<temp.length(); i++) {
            if (temp[i] == '"') {
                num++;
                if (num % 2)
                    cout << "``";
                else
                    cout << "''";
            }
            else
                cout << temp[i];
        }
        cout << endl;
    }

    return 0;
}

2013年6月3日 星期一

圍棋算氣程式

Java code:
import java.util.Scanner;

public class Chi {
    static int[][] board = new int[19][19];
    static boolean[][] gone = new boolean[19][19];
    static boolean[][] isCount = new boolean[19][19];
    static int chessColor;
    static int chiNum = 0;
    
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int x, y;
        
        try {
            System.out.println("請輸入棋盤:");
            for (int i=0; i<board.length; i++) {
                for (int j=0; j<board[i].length; j++)
                    board[i][j] = sc.nextInt();
            }
            System.out.print("請輸入座標: ");
            x = sc.nextInt();
            y = sc.nextInt();
        } finally {
            sc.close();
        }
        if (board[x][y] == 0)
            System.out.println("這個座標沒有任何棋子");
        else {
            chessColor = board[x][y];
            countChi(x, y);
            if (chessColor == 1)
                System.out.println("您算的是黑子的氣");
            else
                System.out.println("您算的是白子的氣");
            System.out.println("共有" + chiNum + "個氣");
        }
    }

    private static void countChi(int x, int y) {
        if (board[x][y] == 0 && !isCount[x][y]) {
            chiNum++;
            isCount[x][y] = true;
        }
        else if (!gone[x][y] && board[x][y] == chessColor) {
            gone[x][y] = true;
            countChi(x - 1, y);
            countChi(x, y - 1);
            countChi(x, y + 1);
            countChi(x + 1, y);
            gone[x][y] = false;
        }
    }
}

範例輸入輸出:



這是老師出的額外題目,題目的要求是輸入一個棋盤,並且指定一個座標,並算出指定座標棋子所在區域的氣。此程式會自動辨識您指定的座標是黑子區域還是白子區域,若您指定黑子就會為您算出黑子的氣;若您指定白子就會為您算出白子的氣,若您指定的地方沒有任何棋子,程式會告訴您這地方沒有任何棋子。此程式的作法就是不斷地搜尋這區域周圍的氣(也就是沒有任何棋子的地方),若已經搜尋過得地方用gone這個布林陣列把它記起來,以避免無限的搜尋,若找到氣了,就把氣數+1然後用布林陣列記住這個地方已經算過氣了,避免未來再重複算一次。
此程式的輸入為一個19 * 19的棋盤,0代表沒有棋子, 1代表黑棋, 2代表白棋,完成後程式會要求您輸入一個座標,格式為(x y),x和y的範圍皆為0~18。輸出為你算的是什麼棋子的氣,以及總共是多少氣。

0-1 Knapsack problem

Java code:
import java.util.LinkedList;
import java.util.List;

class Item {
    int price;
    int weight;
    int pricePerWeight;
    
    public Item(int price, int weight, int pricePerWeight) {
        this.price = price;
        this.weight = weight;
        this.pricePerWeight = pricePerWeight;
    }
}

public class KnapsackProblem {
    static Item[] allItem =
        {new Item(20, 2, 10), new Item(30, 5, 6), new Item(35, 7, 5),
         new Item(12, 3, 4), new Item(3, 1, 3)};
    static int limitWeight = 9;
    static int nowPrice = 0;
    static int nowWeight = 0;
    static int maxPrice = Integer.MIN_VALUE;
    static List<Integer> takeItems = new LinkedList<Integer>();
    static List<Integer> maxPriceTakeItems = new LinkedList<Integer>();
    
    public static void main(String[] args) {
        stealItem(0);
        System.out.print("要拿的物品: ");
        for (int index: maxPriceTakeItems)
            System.out.print(index + 1 + " ");
        System.out.println("\n最大價值: " + maxPrice);
    }

    private static void stealItem(int itemIndex) {
        if (nowWeight <= limitWeight) {
            int boundPrice;
            
            if (nowPrice > maxPrice) {
                maxPrice = nowPrice;
                maxPriceTakeItems.clear();
                for (int index: takeItems)
                    maxPriceTakeItems.add(index);
            }
            boundPrice = calBound(itemIndex);
            if (boundPrice > nowPrice && maxPrice < boundPrice) {
                for (int i=itemIndex; i<allItem.length; i++) {
                    nowPrice += allItem[itemIndex].price;
                    nowWeight += allItem[itemIndex].weight;
                    takeItems.add(itemIndex);
                    stealItem(i + 1);
                    nowPrice -= allItem[itemIndex].price;
                    nowWeight -= allItem[itemIndex].weight;
                    takeItems.remove(takeItems.size() - 1);
                }
            }    
        }
    }

    private static int calBound(int itemIndex) {
        int thePrice = nowPrice;
        int theWeight = nowWeight;
        int i;
        
        for (i=itemIndex; i<allItem.length && theWeight<=limitWeight; i++) {
            thePrice += allItem[i].price;
            theWeight += allItem[i].weight;
        }
        i--;
        thePrice -= allItem[i].price;
        theWeight -= allItem[i].weight;
        return thePrice + allItem[i].pricePerWeight * (limitWeight - theWeight);
    }
}

範例輸入輸出:



0-1背包問題就是解決在物品沒有辦法被分割且背包負重有限的情況下能帶走物品的最大價值。程式裡的類別Item就是代表物品,裡面的field有price(價值), weight(重量), 還有pricePerWeight(單位重量的價值),allItem陣列裡面放的是所有的物品(我偷偷地把它們依照單位重量的價值排序好了XD)。程式的作法就是不斷地拿物品和放物品來找到最大價值,重點是有幾種情況就可以知道物品不要再往下拿了。第一種情況就是總重量已經超過背包的負重,第二種情況就是未來可以拿到的最大價值(利用單位重量的價值計算)等於現在的價值,第三種情況就是未來可以拿到的最大價值比現在已經拿到的最大價值還要少。
因為此程式是解決課本第5章的第33題,所以輸入參數已經是寫死的,輸出為最後拿的物品和最大總價值。

Hamilton Circuit

Java code:
import java.util.LinkedList;
import java.util.List;

public class HamiltonCircuit {
    static boolean[][] graph =
        {{false, true, false, false, true, false, false, false, false, false, false, false},
         {true, false, true, false, false, false, true, true, false, false, false, false},
         {false, true, false, true, false, false, false, true, false, false, false, false},
         {false, false, true, false, false, false, false, false, true, false, false, false},
         {true, false, false, false, false, true, false, false, false, true, false, false},
         {false, false, false, false, true, false, true, false, false, false, true, false},
         {false, true, false, false, false, true, false, true, false, false, false, false},
         {false, true, true, false, false , false, true, false, true, false, false, false},
         {false, false, false, true, false, false, false, true, false, false, false, true},
         {false, false, false, false, true, false, false, false, false, false, true, false},
         {false, false, false, false, false, true, false, false, false, true, false, true},
         {false, false, false, false, false, false, false, false, true, false, true, false}};
    static boolean[] isGone = new boolean[graph.length];
    static List<Integer> path = new LinkedList<Integer>();
    
    public static void main(String[] args) {
        for (int i=0; i<graph.length; i++)
            findCircuit(i);
    }

    private static void findCircuit(int vertex) {
        if (path.size() == graph.length) {
            if (graph[vertex][path.get(0)]) {
                for (int v: path)
                    System.out.print(v + 1 + " ");
                System.out.print((path.get(0) + 1) + "\n\n");
            }
        }
        else {
            isGone[vertex] = true;
            path.add(vertex);
            for (int i=0; i<graph.length; i++) {
                if (graph[vertex][i] && !isGone[i])
                    findCircuit(i);
            }
            isGone[vertex] = false;
            path.remove(path.size() - 1);
        }
    }
}

範例輸入輸出:



Hamilton Circuit 是要在圖上找一個點當作起點,接著把圖上所有的點走訪一遍後回到原點。程式的作法是把所有點都當作起點看看,然後想辦法把每個點都先走過一遍,最後再看看終點能不能回到起點。
因為此程式是解決課本第5章的第26題,所以輸入參數已經寫死在程式裡,之所以沒有範例輸入輸出,是因為這題找不到Hamilton Circuit(如果我的程式沒有錯的話)。

Coloring Problem

Java code:
public class ColoringProblem {
    private enum Color {
        RED, GREEN, WHITE
    }
    static boolean[][] graph =
        {{false, true, false, true, false, false},
         {true, false, true, false, true, false},
         {false, true, false, false, false, true},
         {true, false, false, false, true, false},
         {false, true, false, true, false, true},
         {false, false, true, false, true ,false}};
    static Color[] graphColor = new Color[graph.length];
    static int countComb = 0;
    
    public static void main(String[] args) {
        paintColor(0);
        System.out.println("總共有" + countComb + "種塗色方法");
    }

    private static void paintColor(int vertex) {
        if (vertex < graph.length) {
            for (Color c: Color.values()) {
                boolean isUsed = false;
                
                for (int i=0; i<graph.length; i++) {
                    if (graph[vertex][i] && graphColor[i] == c) {
                        isUsed = true;
                        break;
                    }
                }
                if (!isUsed) {
                    graphColor[vertex] = c;
                    paintColor(vertex + 1);
                    graphColor[vertex] = null;
                }
            }
        }
        else {
            for (int i=0; i<graphColor.length; i++)
                System.out.printf("%-6s", "v" + (i + 1));
            System.out.println();
            for (Color c: graphColor) {
                switch (c) {
                    case RED:
                        System.out.printf("%-6s", "red");
                        break;
                    case GREEN:
                        System.out.printf("%-6s", "green");
                        break;
                    case WHITE:
                        System.out.printf("%-6s", "white");
                }
            }
            System.out.print("\n\n");
            countComb++;
        }
    }
}

範例輸入輸出:



此程式解決的是塗色問題,也就是在一個graph上面,用m個顏色去著色,並且相鄰的點不可以塗上相同的顏色。程式的作法是先選一個點並且從第一個顏色開始嘗試,塗上顏色後在選擇下一個點塗色。塗色時需要檢查相鄰的點有沒有使用一樣的顏色,若有使用一樣的顏色,就必須換色,若沒有顏色可以塗,就必須更改上一個點的顏色。若所有點都成功上色了,就表示找到一個塗色方法了,依照這個方法不斷做下去,就可以找出所有塗色的方法了。
因為此程式是解決課本第5章第18題的問題,所以輸入參數已經寫死在程式裡,輸出為所有的塗色方法和塗色方法的總數目。因為輸出結果過長,所以以上只貼出部份輸出結果。

Sum-of-Subsets

Java code:
import java.util.LinkedList;
import java.util.List;

public class SumOfSubsets {
    static int[] nums = {2, 10, 13, 17, 22, 42};
    static List<Integer> ansList = new LinkedList<Integer>();
    
    public static void main(String[] args) {
        int totalWeight = 52;
        
        System.out.println("以下是所有的解:");
        findAns(totalWeight, 0);
    }

    private static void findAns(int restWeight, int startIndex) {
        if (restWeight > 0) {
            for (int i=startIndex; i<nums.length; i++) {
                ansList.add(nums[i]);
                findAns(restWeight - nums[i], i + 1);
                ansList.remove(ansList.size() - 1);
            }    
        }
        else if (restWeight == 0) {
            for (int i: ansList)
                System.out.print(i + " ");
            System.out.println();
        }
    }
}

範例輸入輸出:



此程式解決的問題是Sum-of-Subsets問題,問題是給一個數字集合S還有一個數字N,找出S裡面所有加起來總和會等於N的組合。解法就是窮舉所有的加法組合看看那一組有符合上述條件。
此程式是解決課本第5章第13題的問題,所以參數已經設死在程式裡。輸出結果就是所有總和為52的組合。

N-Queen

Java code:
import java.util.Scanner;

public class N_Queen {
    static int n;
    static int countQueen = 0;
    static int ansCount = 0;
    static boolean[] colHasQueen, leftSlashHasQueen, rightSlashHasQueen;
    
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        
        try {
            System.out.print("請輸入n: ");
            n = sc.nextInt();
        } finally {
            sc.close();
        }
        colHasQueen = new boolean[n];
        leftSlashHasQueen = new boolean[2 * n - 1];
        rightSlashHasQueen = new boolean[2 * n - 1];
        findQueen(0, 0);
        System.out.println("總共有" + ansCount + "組解");
    }

    private static void findQueen(int row, int col) {
        if (countQueen == n)
            ansCount++;
        else if (col < n) {
            if (!colHasQueen[col] && !leftSlashHasQueen[row - col + n - 1] &&
                    !rightSlashHasQueen[row + col]) {
                colHasQueen[col] = true;
                leftSlashHasQueen[row - col + n - 1] = true;
                rightSlashHasQueen[row + col] = true;
                countQueen++;
                findQueen(row + 1, 0);
                colHasQueen[col] = false;
                leftSlashHasQueen[row - col + n - 1] = false;
                rightSlashHasQueen[row + col] = false;
                countQueen--;
            }
            findQueen(row, col + 1);
        }
    }
}

範例輸入輸出:



此程式解決的問題是經典的n-queen問題,三個布林陣列存的分別是行,  左斜線, 右斜線有沒有被擺過皇后,之所以沒有存列有無擺過皇后是因為這列擺過皇后之後,直接換下一列,所以沒有會碰到同一列的可能。若放置此位置後無法找到皇后共存的組合,則此皇后會往右移一格,若皇后移到此列的盡頭都沒有位置可以擺放則直接回到上一列更改皇后的位置,因為是在n*n的棋盤上擺放n個皇后,所以不可能有任何一列沒有被擺到皇后。
輸入為一個整數n,輸出則為總共有多少種擺放的方式,並沒有去除掉對稱的情況。

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;
}

2013年4月29日 星期一

10093 - An Easy Problem!


Have you heard the fact “The base of every normal number system is 10” ? Of course, I am not talking about number systems like Stern Brockot Number System. This problem has nothing to do with this fact but may have some similarity.  

You will be given an N based integer number R and you are given the guaranty that R is divisible by (N-1). You will have to print the smallest possible value for N. The range for N is 2<=N<=62 and the digit symbols for 62 based number is (0..9 and A..Z and a..z). Similarly, the digit symbols for 61 based number system is (0..9 and A..Z and a..y) and so on.  

Input
Each line in the input file will contain an integer (as defined in mathematics) number of any integer base (2..62). You will have to determine what is the smallest possible base of that number for the given conditions. No invalid number will be given as input.

Output
If number with such condition is not possible output the line “such number is impossible!” For each line of input there will be only a single line of output. The output will always be in decimal number system.

Sample Input
3
5
A

Sample Output
4
6
11


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


這題可能需要知道一個定理會簡單得多,若一個n進位的數可以被n - 1整除,則它每個位數的總和也會被n - 1整除。題目要求找到最小的n,所以我們可以先找到最小的n - 1,這樣就可以找到最小的n。因為n - 1最小要和所有位數裡最大的數相等,所以可以把所有位數裡面最大的數當作找n - 1的起點,接著把61(因為題目說進位最大只到62進位)當作終點,只要一有可以整除所有位數總和的數字出現,它就是最小的n - 1。

c++程式碼:

#include <iostream>
using namespace std;

int main() {
    string input;

    while (cin >> input) {
        int digitSum = 0;
        int ans = -1;
        int maxDigit = -1;

        for (int i=0; i<input.length(); i++){
            int thisDigit;

            if (input[i] >= 'A' && input[i] <= 'Z')
                thisDigit = input[i] - 'A' + 10;
            else if (input[i] >= 'a' && input[i] <= 'z')
                thisDigit = input[i] - 'a' + 36;
            else if (input[i] >= '0' && input[i] <= '9')
                thisDigit = input[i] - '0';
            else
                continue;
            if (thisDigit > maxDigit)
                maxDigit = thisDigit;
            digitSum += thisDigit;
        }
        if (!maxDigit)
            maxDigit = 1;
        for (int i=maxDigit; i<=61; i++) {
            if (!(digitSum % i)) {
                ans = i + 1;
                break;
            }
        }
        if (ans == -1)
            cout << "such number is impossible!\n";
        else
            cout << ans << endl;
    }

    return 0;
}