河海大学常州校区第三届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
****************************************************************/

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值