河海大學常州校區第三屆H-star程序設計大賽決賽

問題 A: Transformations

時間限制: 1 Sec  內存限制: 128 MB
提交: 30  解決: 4
[提交][狀態][討論版] [Edit] [TestData]

題目描述

A square pattern of size N x N (1 <= N <= 10) black and white square tiles is transformed into another square pattern. Write a program that will recognize the minimum transformation that has been applied to the original pattern given the following list of possible transformations:

  • #1: 90 Degree Rotation: The pattern was rotated clockwise 90 degrees.
  • #2: 180 Degree Rotation: The pattern was rotated clockwise 180 degrees.
  • #3: 270 Degree Rotation: The pattern was rotated clockwise 270 degrees.
  • #4: Reflection: The pattern was reflected horizontally (turned into a mirror image of itself by reflecting around a vertical line in the middle of the image).
  • #5: Combination: The pattern was reflected horizontally and then subjected to one of the rotations (#1-#3).
  • #6: No Change: The original pattern was not changed.
  • #7: Invalid Transformation: The new pattern was not obtained by any of the above methods.

In the case that more than one transform could have been used, choose the one with the minimum number above.

輸入

Line 1:

A single integer, N

Line 2..N+1:

N lines of N characters (each either `@' or `-'); this is the square before transformation

Line N+2..2*N+1:

N lines of N characters (each either `@' or `-'); this is the square after transformation

輸出

A single line containing the the number from 1 through 7 (described above) that categorizes the transformation required to change from the `before' representation to the `after' representation.

樣例輸入

3@-@---@@-@-@@----@

樣例輸出

1


#include<cstdio>
#include<cstring>
char a[11][11], b[11][11];
int n, ans[10];
 
void trans() {
  memset(ans, 0, sizeof(ans));
  for(int i = 1; i <= n; i++)
    for(int j = 1; j <= n; j++){
      if(a[i][j] == b[j][n-i+1]) ans[1]++;
      if(a[i][j] == b[n-i+1][n-j+1]) ans[2]++;
      if(a[i][j] == b[n-j+1][i]) ans[3]++;
      if(a[i][j] == b[i][n-j+1]) ans[4]++;
      if(a[i][j] == b[i][j]) ans[6]++;
      if(a[i][n-j+1] == b[j][n-i+1]) ans[5]++;
      if(a[i][n-j+1] == b[n-i+1][n-j+1]) ans[7]++;
      if(a[i][n-j+1] == b[n-j+1][i]) ans[8]++;
    }
 
    for(int i = 1; i <= 8; i++){
        if(ans[i] == n*n){
            if(i < 7) printf("%d\n", i);
            else printf("5\n");
            return ;
        }
    }
    printf("7\n");
}
 
int main(){
    scanf("%d", &n);
    for(int i = 1; i <= n; i++)
       scanf("%s", a[i]+1);
 
    for(int i = 1; i <= n; i++)
       scanf("%s", b[i]+1);
 
    trans();
    return 0;
}
/**************************************************************
    Problem: 1140
    User: auguralpha
    Language: C++
    Result: 正確
    Time:0 ms
    Memory:1032 kb
****************************************************************/

問題 B: Vanya and Cubes

時間限制: 1 Sec  內存限制: 128 MB
提交: 47  解決: 25
[提交][狀態][討論版] [Edit] [TestData]

題目描述

Vanya got n cubes. He decided to build a pyramid from them. Vanya wants to build the pyramid as follows: the top level of the pyramid must consist of 1 cube, the second level must consist of 1+2=3 cubes, the third level must have 1+2+3=6 cubes, and so on. Thus, the i-th level of the pyramid must have 1+2+...+(i-1)+i cubes

Vanya wants to know what is the maximum height of the pyramid that he can make using the given cubes.

輸入

The first line contains integer n (1n104) — the number of cubes given to Vanya.

輸出

Print the maximum possible height of the pyramid in the single line.

樣例輸入

1

樣例輸出

1

提示

Sample Input:


25


Sample Output


4



Illustration to the second sample:



#include <cstdio>
#include <algorithm>
using namespace std;
 
int a[10010];
 
int main(){
    int foo = 0;
    int sum = 0;
    for(int i=1; ; i++){
        if(sum > 10000) break;
        foo += i;
        for(int j=0; j<foo && sum+j<=10000 ; j++){
            a[sum+j] = i-1;
        }
        sum += foo;
    }
    int n;
    while(scanf("%d", &n)==1){
        printf("%d\n", a[n]);
    }
    return 0;
}
 
/**************************************************************
    Problem: 1141
    User: auguralpha
    Language: C++
    Result: 正確
    Time:0 ms
    Memory:1072 kb
****************************************************************/

問題 C: The Same Game

時間限制: 1 Sec  內存限制: 128 MB
提交: 8  解決: 1
[提交][狀態][討論版] [Edit] [TestData]

題目描述

The game named "Same" is a single person game played on a 10 \Theta 15 board. Each square contains a ball colored red (R), green (G), or blue (B). Two balls belong to the same cluster if they have the same color, and one can be reached from another by following balls of the same color in the four directions up, down, left, and right. At each step of the game, the player chooses a ball whose cluster has at least two balls and removes all balls in the cluster from the board. Then, the board is "compressed" in two steps: 
1. Shift the remaining balls in each column down to fill the empty spaces. The order of the balls in each column is preserved. 
2. If a column becomes empty, shift the remaining columns to the left as far as possible. The order of the columns is preserved. 
For example, choosing the ball at the bottom left corner in the sub-board below causes: 

You will be given a number of games in the input. The first line of input contains a positive integer giving the number of games to follow. The initial arrangement of the balls of each game is given one row at a time, from top to bottom. Each row contains 15 characters, each of which is one of "R", "G", or "B", specifying the colors of the balls in the row from left to right. A blank line precedes each game.

輸出

For each game, print the game number, followed by a new line, followed by information about each move, followed by the final score. Each move should be printed in the format: 
Move x at (r,c): removed b balls of color C, got s points. 
where x is the move number, r and c are the row number and column number of the chosen ball, respectively. The rows are numbered from 1 to 10 from the bottom, and columns are numbered from 1 to 15 from the left. b is the number of balls in the cluster removed. C is one of "R", "G", or "B", indicating the color of the balls removed. s is the score for this move. The score does not include the 1000 point bonus if all the balls are removed after the move. 
The final score should be reported as follows: 
Final score: s, with b balls remaining. 
Insert a blank line between the output of each game. Use the plural forms "balls" and "points" even if the corresponding value is 1.

樣例輸入

3 RGGBBGGRBRRGGBGRBGRBGRBGRBGRBGRRRRGBBBRGGRBBBGGRGBGGBRRGGGBGGBGGRRRRRBGGRRRBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBRRRRRRRRRRRRRRRRRRRRRGGGGRRRRRGGGGGGGGGGGGGGGRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGRBGRBGRBGRBGRBGBGRBGRBGRBGRBGRGRBGRBGRBGRBGRBRBGRBGRBGRBGRBGBGRBGRBGRBGRBGRGRBGRBGRBGRBGRBRBGRBGRBGRBGRBGBGRBGRBGRBGRBGRGRBGRBGRBGRBGRBRBGRBGRBGRBGRBG

樣例輸出

Game 1: Move 1 at (4,1): removed 32 balls of color B, got 900 points. Move 2 at (2,1): removed 39 balls of color R, got 1369 points. Move 3 at (1,1): removed 37 balls of color G, got 1225 points. Move 4 at (3,4): removed 11 balls of color B, got 81 points. Move 5 at (1,1): removed 8 balls of color R, got 36 points. Move 6 at (2,1): removed 6 balls of color G, got 16 points. Move 7 at (1,6): removed 6 balls of color B, got 16 points. Move 8 at (1,2): removed 5 balls of color R, got 9 points. Move 9 at (1,2): removed 5 balls of color G, got 9 points. Final score: 3661, with 1 balls remaining. Game 2: Move 1 at (1,1): removed 30 balls of color G, got 784 points. Move 2 at (1,1): removed 30 balls of color R, got 784 points. Move 3 at (1,1): removed 30 balls of color B, got 784 points. Move 4 at (1,1): removed 30 balls of color G, got 784 points. Move 5 at (1,1): removed 30 balls of color R, got 784 points. Final score: 4920, with 0 balls remaining. Game 3: Final score: 0, with 150 balls remaining. 
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
 
using namespace std;
 
char map[20][20];
bool vis[20][20];
int leave, score;
int rx, ry, rn, cnt;
int dir[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
 
bool inMap(int x, int y)
{
    return (x >= 0 && x < 10 && y >= 0 && y < 15);
}
 
void dfs(int x, int y)
{
    vis[x][y] = true;
    cnt++;
    for (int i = 0; i < 4; ++i)
    {
        int nx = x + dir[i][0];
        int ny = y + dir[i][1];
        if (inMap(nx, ny) && map[nx][ny] == map[x][y] && !vis[nx][ny])
        {
            dfs(nx, ny);
        }
    }
}
 
bool choose()
{
    memset(vis, false, sizeof(vis));
    rn = 0;
    for (int i = 0; i < 15; ++i)
    {
        for (int j = 9; j >= 0; --j)
        {
            if (map[j][i] == ' ' || vis[j][i]) continue;
            cnt = 0;
            dfs(j, i);
            if (cnt > rn)
            {
                rx = j; ry = i;
                rn = cnt;
            }
        }
    }
    return rn >= 2;
}
 
void remove(int x, int y)
{
    char color = map[x][y];
    map[x][y] = ' ';
    for (int i = 0; i < 4; ++i)
    {
        int nx = x + dir[i][0];
        int ny = y + dir[i][1];
        if (inMap(nx, ny) && map[nx][ny] == color)
            remove(nx, ny);
    }
}
 
void shift()
{
    for (int i = 0; i < 15; ++i)
    {
        int pos = 9;
        for (int j = 9; j >= 0; --j)
        {
            if (map[j][i] != ' ')
                map[pos--][i] = map[j][i];
        }
        while (pos >= 0)
        {
            map[pos][i] = ' ';
            pos--;
        }
    }
    int pos = 0;
    for (int i = 0; i < 15; ++i)
    {
        if (map[9][i] != ' ')
        {
            for (int j = 0; j < 10; ++j)
            {
                map[j][pos] = map[j][i];
            }
            pos++;
        }
    }
    while (pos < 15)
    {
        for (int i = 0; i < 10; ++i)
            map[i][pos] = ' ';
        pos++;
    }
}
 
int main()
{
    int t;
    scanf("%d", &t);
    for (int cas = 1; cas <= t; ++cas)
    {
        leave = 10 * 15;
        score = 0;
        int step = 0;
        for (int i = 0; i < 10; ++i)
        {
            scanf("%s", map[i]);
        }
        printf("Game %d:\n\n", cas);
        while (choose())
        {
            step++;
            printf("Move %d at (%d,%d): removed %d balls of color %c, got %d points.\n", step, 10 - rx, ry + 1, rn, map[rx][ry], (rn - 2) * (rn - 2));
            score += (rn - 2) * (rn - 2);
            leave -= rn;
            remove(rx, ry);
            shift();
        }
        if (leave == 0) score += 1000;
        printf("Final score: %d, with %d balls remaining.\n", score, leave);
        if (cas != t) printf("\n");
    }
}
 
/**************************************************************
    Problem: 1142
    User: auguralpha
    Language: C++
    Result: 正確
    Time:0 ms
    Memory:1504 kb
****************************************************************/


問題 D: To Miss Our Children Time

時間限制: 1 Sec  內存限制: 128 MB
提交: 6  解決: 1
[提交][狀態][討論版] [Edit] [TestData]

題目描述

Do you remember our children time? When we are children, we are interesting in almost everything around ourselves. A little thing or a simple game will brings us lots of happy time! LLL is a nostalgic boy, now he grows up. In the dead of night, he often misses something, including a simple game which brings him much happy when he was child. Here are the game rules: There lies many blocks on the ground, little LLL wants build "Skyscraper" using these blocks. There are three kinds of blocks signed by an integer d. We describe each block's shape is Cuboid using four integers ai, bi, ci, di. ai, bi are two edges of the block one of them is length the other is width. ci is 
thickness of the block. We know that the ci must be vertical with earth ground. di describe the kind of the block. When di = 0 the block's length and width must be more or equal to the block's length and width which lies under the block. When di = 1 the block's length and width must be more or equal to the block's length which lies under the block and width and the block's area must be more than the block's area which lies under the block. When di = 2 the block length and width must be more than the block's length and width which lies under the block. Here are some blocks. Can you know what's the highest "Skyscraper" can be build using these blocks?

輸入

The input has many test cases. 
For each test case the first line is a integer n ( 0< n <= 1000) , the number of blocks. 
From the second to the n+1'th lines , each line describing the i
1'th block's a,b,c,d (1 =< ai,bi,ci <= 10^8 , d = 0 or 1 or 2). 
The input end with n = 0.

輸出

Output a line contains a integer describing the highest "Skyscraper"'s height using the n blocks.

樣例輸入

3
10 10 12 0
10 10 12 1
10 10 11 2

2
10 10 11 1
10 10 11 1

0

樣例輸出

24
11

#include <cstdio>
#include <algorithm>
#include <iostream>
using namespace std;
  
const int maxn = 1010;
struct Block{
    int a, b, c, d;
}block[maxn];
long long dp[maxn];
  
bool cmp(Block aa, Block bb);
  
int main(){
    int n;
    while(scanf("%d", &n)!=EOF && n){
        for(int i = 0; i < n; ++i){
            scanf("%d%d%d%d", &block[i].a, &block[i].b, &block[i].c, &block[i].d);
            if(block[i].a < block[i].b){
                swap(block[i].a, block[i].b);
            }
        }
        sort(block, block+n, cmp);
  
        for(int i = 0; i < n; ++i){
            dp[i] = block[i].c;
            for(int j = 0; j < i; ++j){
                if(block[i].d == 0){
                    if(block[i].a >= block[j].a && block[i].b >= block[j].b){
                        dp[i] = max(dp[j]+block[i].c, dp[i]);
                    }
                }
                else if(block[i].d == 1){
                    if(block[i].a>=block[j].a && block[i].b>=block[j].b && (block[i].a>block[j].a||block[i].b>block[j].b)){
                        dp[i] = max(dp[j]+block[i].c, dp[i]);
                    }
                }
                else{
                    if(block[i].a > block[j].a && block[i].b > block[j].b){
                        dp[i] = max(dp[j]+block[i].c, dp[i]);
                    }
                }
            }
        }
  
        long long ans = 0;
        for(int i = 0; i < n; ++i){
            ans = max(ans, dp[i]);
        }
  
        cout << ans << endl;
    }
    return 0;
}
  
bool cmp(Block aa, Block bb){
    if(aa.a == bb.a){
        if(aa.b == bb.b){
            return aa.d > bb.d;
        }
        return aa.b < bb.b;
    }
    return aa.a < bb.a;
}
/**************************************************************
    Problem: 1143
    User: auguralpha
    Language: C++
    Result: 正確
    Time:7 ms
    Memory:1532 kb
****************************************************************/

問題 E: Cow Tours

時間限制: 1 Sec  內存限制: 128 MB
提交: 5  解決: 3
[提交][狀態][討論版] [Edit] [TestData]

題目描述

農民 John的農場裏有很多牧區。有的路徑連接一些特定的牧區。一片所有連通的牧區稱爲一個牧場。但是就目前而言,你能看到至少有兩個牧場通過任何路徑都不連通。這樣,Farmer John就有多個牧場了。
John想在牧場裏添加一條路徑(注意,恰好一條)。對這條路徑有以下限制:
一個牧場的直徑就是牧場中最遠的兩個牧區的距離(本題中所提到的所有距離指的都是最短的距離)。考慮如下的有5個牧區的牧場,牧區用“*”表示,路徑用直線表示。每一個牧區都有自己的座標:

這個牧場的直徑大約是12.07106, 最遠的兩個牧區是A和E,它們之間的最短路徑是A-B-E。
這裏是另一個牧場:
                        
添加C至G一條路徑後便是:

整個牧場直徑約爲22.071068。 在目前的情景中,他剛好有兩個牧場。John將會在兩個牧場中各選一個牧區,然後用一條路徑連起來,使得連通後這個新的更大的牧場有最小的直徑。
注意,如果兩條路徑中途相交,我們不認爲它們是連通的。只有兩條路徑在同一個牧區相交,我們才認爲它們是連通的。
輸入文件包括牧區、它們各自的座標,還有一個如下的對稱鄰接矩陣:
A  B  C  D  E  F  G  H
A  0  1  0  0  0  0  0  0
B  1  0  1  1  1  0  0  0
C  0  1  0  0  1  0  0  0
D  0  1  0  0  1  0  0  0
E  0  1  1  1  0  0  0  0
F  0  0  0  0  0  0  1  0
G  0  0  0  0  0  1  0  1
H  0  0  0  0  0  0  1  0
其他鄰接表中可能直接使用行列而不使用字母來表示每一個牧區。輸入數據中不包括牧區的名字。
輸入文件至少包括兩個不連通的牧區。
請編程找出一條連接兩個不同牧場的路徑,使得連上這條路徑後,這個更大的新牧場有最小的直徑。輸出在所有牧場中最小的可能的直徑。

輸入

第1行: 一個整數N (1 <= N <= 150), 表示牧區數

第2到N+1行: 每行兩個整數X,Y (0 <= X ,Y<= 100000), 表示N個牧區的座標。注意每個 牧區的座標都是不一樣的。

第N+2行到第2*N+1行: 每行包括N個數字(0或1) 表示如上文描述的對稱鄰接矩陣。

輸出

只有一行,包括一個實數,表示所求直徑。數字保留六位小數。

只需要打到小數點後六位即可,不要做任何特別的四捨五入處理。

樣例輸入

8
10 10
15 10
20 10
15 15
20 15
30 15
25 10
30 10
01000000
10111000
01001000
01001000
01110000
00000010
00000101
00000010

樣例輸出

22.071068
#include<cstdio>
#include<cstring>
#include<vector>
#include<cmath>
using namespace std;
typedef long long LL;
const int N = 151;
const int INF = 0x3f3f3f3f;
double dist[N][N];
bool vis[N];
char s[N][N];
int x[N], y[N];
int n;
double longest[N];
vector<vector<int > > g;
vector<double > farest;
  
void solve1(int k, vector<int > &g){
    vis[k] = true;
    g.push_back(k);
    for(int i = 0; i < n; ++i){
        if(s[k][i] == '1' && !vis[i]){
            solve1(i, g);
        }
    }
}
  
double CalDist(int i, int j){
    return sqrt((x[j]-x[i])*(x[j]-x[i]) + (y[j]-y[i])*(y[j]-y[i]));
}
  
int main(){
//    freopen("cowtour.in", "r", stdin);
//    freopen("cowtour.out", "w", stdout);
    scanf("%d", &n);
    for(int i = 0; i < n; ++i){
        scanf("%d%d", &x[i], &y[i]);
    }
    for(int i = 0; i < n; ++i){
        scanf("%s", s[i]);
    }
    memset(vis, false, sizeof(vis));
  
    for(int i = 0; i < n; ++i){
        vector<int > q;
        if(!vis[i]){
            solve1(i, q);
            g.push_back(q);
        }
    }
  
    for(int i = 0; i < n; ++i){
        for(int j = 0; j < n; ++j){
            dist[i][j] = INF;
        }
    }
    memset(longest, 0, sizeof(longest));
    for(int x = 0; x < g.size(); ++x){
        vector<int > point = g[x];
        for(int i = 0; i < point.size(); ++i){
            dist[point[i]][point[i]] = 0;
            for(int j = 0; j < point.size(); ++j){
                if(s[point[i]][point[j]] == '1'){
                    dist[point[i]][point[j]] = CalDist(point[i], point[j]);
                }
            }
       }
  
        for(int k = 0; k < point.size(); ++k){
            for(int i = 0; i < point.size(); ++i){
                for(int j = 0; j < point.size(); ++j){
                    if(i != j && dist[point[i]][point[k]] + dist[point[k]][point[j]] < dist[point[i]][point[j]]){
                        dist[point[i]][point[j]] = dist[point[i]][point[k]] + dist[point[k]][point[j]];
                    }
                }
            }
        }
  
        double ans1 = 0;
        for(int i = 0; i < point.size(); ++i){
            for(int j = 0; j < point.size(); ++j){
                if(dist[point[i]][point[j]] > ans1){
                    ans1 = dist[point[i]][point[j]];
                }
                if(dist[point[i]][point[j]] > longest[point[i]]){
                    longest[point[i]] = dist[point[i]][point[j]];
                }
            }
        }
        farest.push_back(ans1);
    }
  
    /*
    for(int i = 0; i < farest.size(); ++i){
        printf("%lf ", farest[i]);
    }
    for(int i = 0; i < n; ++i){
        printf("%lf ", longest[i]);
    }*/
  
    double ans = 1e9;
    for(int i = 0; i < g.size(); ++i){
        for(int j = i+1; j < g.size(); ++j){
            vector<int > u = g[i], v = g[j];
            double ans1 = 1e9;
            for(int l = 0; l < u.size(); ++l){
                for(int k = 0; k < v.size(); ++k){
                    double tmp = CalDist(u[l], v[k]) + longest[u[l]] + longest[v[k]];
                    if(tmp < farest[i]) tmp = farest[i];
                    if(tmp < farest[j]) tmp = farest[j];
                    if(tmp < ans1){
                        ans1 = tmp;
                    }
                }
            }
            if(ans1 < ans){
                ans = ans1;
            }
  
        }
    }
    printf("%.6lf\n", ans);
    return 0;
}
/**************************************************************
    Problem: 1144
    User: auguralpha
    Language: C++
    Result: 正確
    Time:0 ms
    Memory:1296 kb
****************************************************************/

問題 F: Milking Cows

時間限制: 1 Sec  內存限制: 256 MB
提交: 133  解決: 16
[提交][狀態][討論版] [Edit] [TestData]

題目描述

三個農民每天清晨5點起牀,然後去牛棚給3頭牛擠奶。第一個農民在300秒(從5點開始計時)給他的牛擠奶,一直到1000秒。第二個農民在700秒開始,在 1200秒結束。第三個農民在1500秒開始2100秒結束。期間最長的至少有一個農民在擠奶的連續時間爲900秒(從300秒到1200秒),而最長的無人擠奶的連續時間(從擠奶開始一直到擠奶結束)爲300秒(從1200秒到1500秒)。
你的任務是編一個程序,讀入一個有民(1 <= N <= 5000)擠N頭牛的工作時間列表,計算以下兩點(均以秒爲單位):
    最長至少有一人在擠奶的時間段。
    最長的無人擠奶的時間段。(從有人擠奶開始算起)

輸入

    第1行:一個整數N。
    第2至第N+1行:每行兩個小於1000000的非負整數,表示一個農民的開始時刻與結束時刻。

輸出

一行,兩個整數,即題目所要求的兩個答案。

樣例輸入

3
300 1000
700 1200
1500 2100

樣例輸出

900 300
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 5001;
  
typedef struct node{
    int l, r;
    bool operator< (const node& s) const{
        if(l != s.l) return l < s.l;
        return r < s.r;
    }
}node;
node a[N];
  
int main(){
    int n;
    scanf("%d", &n);
  
    for(int i = 0; i < n; ++i){
        scanf("%d%d", &a[i].l, &a[i].r);
    }
    sort(a, a+n);
  
    int v1 = a[0].r - a[0].l, v2 = 0;
    int s = a[0].l, e = a[0].r;
    for(int i = 1; i < n; ++i){
        if(a[i].l > e){
            if(a[i].l - e > v2){
                v2 = a[i].l - e;
            }
            s = a[i].l, e = a[i].r;
        }
        else{
            if(a[i].r > e){
                if(a[i].r - s > v1){
                    v1 = a[i].r - s;
                }
                e = a[i].r;
            }
        }
    }
    printf("%d %d\n", v1, v2);
    return 0;
}
/**************************************************************
    Problem: 1145
    User: auguralpha
    Language: C++
    Result: 正確
    Time:0 ms
    Memory:1076 kb
****************************************************************/

問題 G: Trie樹

時間限制: 1 Sec  內存限制: 128 MB
提交: 19  解決: 13
[提交][狀態][討論版] [Edit] [TestData]

題目描述

小Hi和小Ho是一對好朋友,出生在信息化社會的他們對編程產生了莫大的興趣,他們約定好互相幫助,在編程的學習道路上一同前進。
這一天,他們遇到了一本詞典,於是小Hi就向小Ho提出了那個經典的問題:“小Ho,你能不能對於每一個我給出的字符串,都在這個詞典裏面找到以這個字符串開頭的所有單詞呢?”
身經百戰的小Ho答道:“怎麼會不能呢!你每給我一個字符串,我就依次遍歷詞典裏的所有單詞,檢查你給我的字符串是不是這個單詞的前綴不就是了?”
小Hi笑道:“你啊,還是太年輕了!~假設這本詞典裏有10萬個單詞,我詢問你一萬次,你得要算到哪年哪月去?”
小Ho低頭算了一算,看着那一堆堆的0,頓時感覺自己這輩子都要花在上面了...
小Hi看着小Ho的囧樣,也是繼續笑道:“讓我來提高一下你的知識水平吧~你知道樹這樣一種數據結構麼?”
小Ho想了想,說道:“知道~它是一種基礎的數據結構,就像這裏說的一樣!”
小Hi滿意的點了點頭,說道:“那你知道我怎麼樣用一棵樹來表示整個詞典麼?”
小Ho搖搖頭表示自己不清楚。
提示一:Trie樹的建立
“你看,我們現在得到了這樣一棵樹,那麼你看,如果我給你一個字符串ap,你要怎麼找到所有以ap開頭的單詞呢?”小Hi又開始考校小Ho。
“唔...一個個遍歷所有的單詞?”小Ho還是不忘自己最開始提出來的算法。
“笨!這棵樹難道就白構建了!”小Hi教訓完小Ho,繼續道:“看好了!”
提示二:如何使用Trie樹
提示三:在建立Trie樹時同時進行統計!
“那麼現在!趕緊去用代碼實現吧!”小Hi如是說道

輸入

輸入的第一行爲一個正整數n,表示詞典的大小,其後n行,每一行一個單詞(不保證是英文單詞,也有可能是火星文單詞哦),單詞由不超過10個的小寫英文字母組成,可能存在相同的單詞,此時應將其視作不同的單詞。接下來的一行爲一個正整數m,表示小Hi詢問的次數,其後m行,每一行一個字符串,該字符串由不超過10個的小寫英文字母組成,表示小Hi的一個詢問。
n, m<=100000,詞典的字母表大小<=26.

輸出

對於小Hi的每一個詢問,輸出一個整數Ans,表示詞典中以小Hi給出的字符串爲前綴的單詞的個數。

樣例輸入

5
babaab
babbbaaaa
abba
aaaaabaa
babaababb
5
babb
baabaaa
bab
bb
bbabbaab

樣例輸出

1
0
3
0
0
#include<iostream>
using namespace std;
typedef struct Node{
    char c;
    int count;
    Node* down;
    Node* left;
}TNode;
int main()
{
    int n;
    cin>>n;
    string word;
    TNode *TriTree=new TNode;
    TNode *tempnode;
    TNode *curp;
        TNode *curpt;
     TriTree->count=n;
     TriTree->down=NULL;
     TriTree->left=NULL;
    for(int i=0;i<n;++i)
    {
        cin>>word;
        curp=TriTree;
        for(string::iterator it=word.begin();it!=word.end();++it)
        {
            curpt=curp->down;
            if(curpt==NULL)
            {
              tempnode=new TNode;
              tempnode->c=*it;
              tempnode->count=1;
              tempnode->down=NULL;
              tempnode->left=NULL;
              curp->down=tempnode;
              curp=curp->down;
            }
            else
            {
             while(curpt->left!=NULL)
             {
               if(curpt->c==*it)
                {
                    (curpt->count)++;
                    curp=curpt;
                    break;
                }
              curpt=curpt->left;
             }
             if(curpt->left==NULL)
             {
                 if(curpt->c==*it)
                {
                    (curpt->count)++;
                    curp=curpt;
                }
                else{
                  tempnode=new TNode;
                   tempnode->c=*it;
                    tempnode->count=1;
                   tempnode->down=NULL;
                   tempnode->left=NULL;
                  curpt->left=tempnode;
                  curp=curpt->left;
                }
             }
            }
 
        }
    }
 
int m;
cin>>m;
 int sumpre;
 string testpre;
 for(int i=0;i<m;++i)
 {
 curp=TriTree;
 cin>>testpre;
 for(string::iterator it=testpre.begin();it!=testpre.end();++it)
 {
    curpt=curp->down;
    if(curpt==NULL)
    {
        sumpre=0;
        break;
    }
    else{
         while(curpt!=NULL)
             {
               if(curpt->c==*it)
                {
                    sumpre=curpt->count;
                    curp=curpt;
                    break;
                }
              curpt=curpt->left;
             }
             if(curpt==NULL)
             {
                sumpre=0;
                break;
             }
    }
 
 }
 cout<<sumpre<<endl;
 }
}
 
 
 
/**************************************************************
    Problem: 1146
    User: auguralpha
    Language: C++
    Result: 正確
    Time:0 ms
    Memory:1504 kb
****************************************************************/

問題 H: Zero Sum

時間限制: 1 Sec  內存限制: 128 MB
提交: 18  解決: 5
[提交][狀態][討論版] [Edit] [TestData]

題目描述

請考慮一個由1到N(N=3, 4, 5 ... 9)的數字組成的遞增數列:1 2 3 ... N。 現在請在數列中插入“+”表示加,或者“-”表示減,“ ”表示空白(例如1-2 3就等於1-23),來將每一對數字組合在一起(請不要在第一個數字前插入符號)。 計算該表達式的結果並判斷其值是否爲0。 請你寫一個程序找出所有產生和爲零的長度爲N的數列。

輸入

單獨的一行表示整數N (3 <= N <= 9)。

輸出

按照ASCII碼的順序,輸出所有在每對數字間插入“+”, “-”, 或 “ ”後能得到結果爲零的數列。

樣例輸入

7

樣例輸出

1+2-3+4-5-6+7
1+2-3-4+5+6-7
1-2 3+4+5+6+7
1-2 3-4 5+6 7
1-2+3+4-5+6-7
1-2-3-4-5+6+7
#include<cstdio>
#include<cstring>
#include<vector>
#include<string>
#include<algorithm>
using namespace std;
int n;
vector<string > good;
char ans[25];
 
bool cmp(string a, string b){
    return a < b;
}
 
void solve(int sum, int k, int cnt, int op){//當前和爲sum, 當前計算到1~N中的k,  cnt是記錄結果的遊標,當前保存的符號爲op,  -1表示+,-2表示-
    int s = 0, i;
    bool flag = false;
    for(i = k; i <= n; ++i){
        s = s*10 + i;
        if(flag){
            ans[cnt++] = -3;//blank
        }
        ans[cnt++] = i;
        flag = true;
       // printf("s  = %d\n", s);
 
        if(i < n){
            if(op == -1){//+
                ans[cnt] = -1;
                solve(sum+s, i+1, cnt+1, -1);
                ans[cnt] = -2;
                solve(sum+s, i+1, cnt+1, -2);
            }
            else{//-
                ans[cnt] = -1;
                solve(sum-s, i+1, cnt+1, -1);
                ans[cnt] = -2;
                solve(sum-s, i+1, cnt+1, -2);
            }
        }
 
        else{
            int tmp;
            if(op == -1){
                tmp = sum + s;
            }
            else if(op == -2){
                tmp = sum - s;
            }
            if(tmp == 0){
                string res = "";
                for(int j = 0; j < cnt; ++j){
                    if(ans[j] > 0) res += ans[j] + '0';
                    if(ans[j] == -1) res += "+";
                    if(ans[j] == -2) res += "-";
                    if(ans[j] == -3) res += " ";
                }
                good.push_back(res);
            }
            return ;
        }
    }
}
 
int main(){
    scanf("%d", &n);
    good.clear();
    solve(0, 1, 0, -1);
    sort(good.begin(), good.end(), cmp);
    for(int i = 0; i < good.size(); ++i){
        printf("%s\n", good[i].c_str());
    }
    return 0;
}
 
/**************************************************************
    Problem: 1147
    User: auguralpha
    Language: C++
    Result: 正確
    Time:0 ms
    Memory:1072 kb
****************************************************************/

問題 I: Overfencing

時間限制: 1 Sec  內存限制: 128 MB
提交: 25  解決: 3
[提交][狀態][討論版] [Edit] [TestData]

題目描述

農夫John在外面的田野上搭建了一個巨大的用柵欄圍成的迷宮。幸運的是,他在迷宮的邊界上留出了兩段柵欄作爲迷宮的出口。更幸運的是,他所建造的迷宮是一個“完美的”迷宮:即你能從迷宮中的任意一點找到一條走出迷宮的路。給定迷宮的寬度W(1<=W<=38)及高度H(1<=H<=100)。 2*H+1行,每行2*W+1的字符以下面給出的格式表示一個迷宮。然後計算從迷宮中最“糟糕”的那一個點走出迷宮所需的步數(就是從最“糟糕”的一點,走出迷宮的最少步數)。(即使從這一點以最優的方式走向最靠近的出口,它仍然需要最多的步數)當然了,牛們只會水平或垂直地在X或Y軸上移動,他們從來不走對角線。每移動到一個新的方格算作一步(包括移出迷宮的那一步)這是一個W=5,H=3的迷宮:

如上圖例子,柵欄的柱子只出現在奇數行或奇數列。每個迷宮只有兩個出口。

輸入

第一行: W和H(用空格隔開)
第二行至第2 * H + 1行: 每行2 * W + 1個字符表示迷宮

輸出

輸出走出迷宮的最少步數

樣例輸入

5 3
+-+-+-+-+-+
|         |
+-+ +-+ + +
|     | | |
+ +-+-+ + +
| |     |  
+-+ +-+-+-+

樣例輸出

9
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int N = 210;
char s[N][N];
bool vis[N][N];
int dist[N][N], dist2[N][N];
struct node{
    int x, y;
    int cnt;
};
queue<node > q;
int m, n;
 
void solve(int sx, int sy, int dist[][N]){
    memset(dist, -1, sizeof(dist));
    memset(vis, false, sizeof(vis));
    while(!q.empty()) q.pop();
    node tmp;
    tmp.x = sx, tmp.y = sy, tmp.cnt = 1;
    dist[sx][sy] = 1, vis[sx][sy] = true;
    q.push(tmp);
    while(!q.empty()){
        node p = q.front();
//        printf("%d %d %d\n", p.x, p.y, p.cnt);
        q.pop();
        int tx = p.x, ty = p.y;
        if(tx >= 3){
            if(s[tx-1][ty] == ' ' && !vis[tx-2][ty]){
                vis[tx-2][ty] = true;
                tmp.x = tx-2, tmp.y = ty, tmp.cnt = p.cnt + 1;
                q.push(tmp);
                dist[tx-2][ty] = tmp.cnt;
            }
        }
 
        if(tx <= (m<<1)-3){
            if(s[tx+1][ty] == ' ' && !vis[tx+2][ty]){
                vis[tx+2][ty] = true;
                tmp.x = tx+2, tmp.y = ty, tmp.cnt = p.cnt + 1;
                q.push(tmp);
                dist[tx+2][ty] = tmp.cnt;
            }
        }
 
        if(ty >= 3){
            if(s[tx][ty-1] == ' ' && !vis[tx][ty-2]){
                vis[tx][ty-2] = true;
                tmp.x = tx, tmp.y = ty-2, tmp.cnt = p.cnt + 1;
                q.push(tmp);
                dist[tx][ty-2] = tmp.cnt;
            }
        }
 
        if(ty <= (n<<1)-3){
            if(s[tx][ty+1] == ' ' && !vis[tx][ty+2]){
                vis[tx][ty+2] = true;
                tmp.x = tx, tmp.y = ty+2, tmp.cnt = p.cnt + 1;
                q.push(tmp);
                dist[tx][ty+2] = tmp.cnt;
            }
        }
    }
}
 
int main(){
//    freopen("maze1.in", "r", stdin);
//    freopen("maze1.out", "w", stdout);
    scanf("%d%d", &n, &m);
    getchar();
    for(int i = 0; i < (m<<1|1); ++i){
        gets(s[i]);
    //    puts(s[i]);
    }
 
    int cnt = 0, x[2], y[2];
    for(int i = 1; i < (n<<1|1); i += 2){
        if(cnt == 2) break;
        if(s[0][i] == ' '){
            x[cnt] = 1, y[cnt] = i;
            ++cnt;
        }
    }
    for(int i = 1; i < (n<<1|1); i += 2){
        if(cnt == 2) break;
        if(s[m<<1][i] == ' '){
            x[cnt] = (m<<1) - 1, y[cnt] = i;
            ++cnt;
        }
    }
 
    for(int i = 1; i < (m<<1|1); i += 2){
        if(cnt == 2) break;
        if(s[i][0] == ' '){
            x[cnt] = i, y[cnt] = 1;
            ++cnt;
        }
    }
    for(int i = 1; i < (m<<1|1); i += 2){
        if(cnt == 2) break;
        if(s[i][n<<1] == ' '){
            x[cnt] = i, y[cnt] = (n<<1) - 1;
            ++cnt;
        }
    }
 
    solve(x[0], y[0], dist);
    solve(x[1], y[1], dist2);
    int ans = -1;
    for(int i = 1; i < (m<<1|1); i += 2){
        for(int j = 1; j < (n<<1|1); j += 2){
            int res = dist[i][j];
            if(res > dist2[i][j]){
                res = dist2[i][j];
            }
            if(res > ans){
                ans = res;
            }
        }
    }
    printf("%d\n", ans);
    return 0;
}
 
/**************************************************************
    Problem: 1148
    User: auguralpha
    Language: C++
    Result: 正確
    Time:0 ms
    Memory:1496 kb
****************************************************************/

問題 J: Ordered Fractions

時間限制: 1 Sec  內存限制: 128 MB
提交: 57  解決: 22
[提交][狀態][討論版] [Edit] [TestData]

題目描述

輸入一個自然數N,對於一個最簡分數a/b(分子和分母互質的分數),滿足1<=b<=N,0<=a/b<=1,請找出所有滿足條件的分數。
這有一個例子,當N=5時,所有解爲:
0/1 1/5 1/4 1/3 2/5 1/2 3/5 2/3 3/4 4/5 1/1
給定一個自然數N,1<=n<=160,請編程按分數值遞增的順序輸出所有解。
注:①0和任意自然數的最大公約數就是那個自然數②互質指最大公約數等於1的兩個自然數。

輸入

單獨的一行 一個自然數N(1..160)

輸出

每個分數單獨佔一行,按照大小次序排列

樣例輸入

5

樣例輸出

0/1
1/5
1/4
1/3
2/5
1/2
3/5
2/3
3/4
4/5
1/1

#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
int n;
 
void solve(int x1, int y1, int x2, int y2){
    int x = x1 + x2, y = y1 + y2;
    if(y > n){
        return ;
    }
    solve(x1, y1, x, y);
    printf("%d/%d\n", x, y);
    solve(x, y, x2, y2);
}
 
int main(){
    scanf("%d", &n);
    printf("0/1\n");
    solve(0, 1, 1, 1);
    printf("1/1\n");
    return 0;
}
 
/**************************************************************
    Problem: 1149
    User: auguralpha
    Language: C++
    Result: 正確
    Time:0 ms
    Memory:1032 kb
****************************************************************/

發佈了35 篇原創文章 · 獲贊 45 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章