Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 25366 | Accepted: 12778 |
Description
Input
Output
Sample Input
10 12 W........WW. .WWW.....WWW ....WW...WW. .........WW. .........W.. ..W......W.. .W.W.....WW. W.W.W.....W. .W.W......W. ..W.......W.
Sample Output
3
Hint
Source
思路:
园子里下了雨有积水,八连通的积水被认为是连接在一起的。求园子里有多少水洼。
确实是比较经典的深搜。
代码:
Source Code Problem: 2386 User: liangrx06 Memory: 1320K Time: 16MS Language: G++ Result: Accepted Source Code #include <iostream> #include <cstdio> #include <algorithm> using namespace std; #define N 100 int n, m; char lake[N][N+1]; void input() { cin >> n >> m; for (int i=0; i<n; i++) { cin >> lake[i]; } } void dfs(int x, int y) { lake[x][y] = '.'; for (int dx=-1; dx<=1; dx++) { for (int dy=-1; dy<=1; dy++) { if (!dx && !dy) continue; int nx = x + dx, ny = y + dy; if (0 <= nx && nx < n && 0 <= ny && ny < m && lake[nx][ny] == 'W') dfs(nx, ny); } } } void solve() { int res = 0; for (int i=0; i<n; i++) { for (int j=0; j<m; j++) { if (lake[i][j] == 'W') { dfs(i, j); res ++; } } } printf("%d\n", res); } int main(void) { input(); solve(); return 0; }
Time Limit: 1000MS | Memory Limit: 30000K | |
Total Submissions: 27075 | Accepted: 14714 |
Description
Input
Output
Sample Input
6 9 ....#. .....# ...... ...... ...... ...... ...... #@...# .#..#. 11 9 .#......... .#.#######. .#.#.....#. .#.#.###.#. .#.#..@#.#. .#.#####.#. .#.......#. .#########. ........... 11 6 ..#..#..#.. ..#..#..#.. ..#..#..### ..#..#..#@. ..#..#..#.. ..#..#..#.. 7 7 ..#.#.. ..#.#.. ###.### ...@... ###.### ..#.#.. ..#.#.. 0 0
Sample Output
45 59 6 13
Source
思路:
人的初始位置是@,点代表黑色地板可以走,#代表白色不能走,每次只可以上下左右走一步。问能到达多少黑色地板。
深搜即可。
代码:
Source Code Problem: 1979 User: liangrx06 Memory: 212K Time: 0MS Language: C++ Result: Accepted Source Code #include <iostream> #include <cstdio> using namespace std; #define N 20 int n, m; char tile[N][N+1]; int number; void dfs(int x, int y) { tile[x][y] = '#'; int d[4][2] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}}; for (int i = 0; i < 4; i ++) { int nx = x + d[i][0], ny = y + d[i][1]; if (0 <= nx && nx < n && 0 <= ny && ny < m && tile[nx][ny] == '.') { number ++; dfs(nx, ny); } } } void solve() { char *c; int bx, by; for (int i=0; i<n; i++) { if ( c = strstr(tile[i], "@") ) { bx = i; by = c - tile[i]; } } number = 1; dfs(bx, by); printf("%d\n", number); } int main(void) { while (cin >> m >> n) { if (!m && !n) break; for (int i=0; i<n; i++) { cin >> tile[i]; } solve(); } return 0; }
Time Limit: 1000MS | Memory Limit: 65536KB | 64bit IO Format: %lld & %llu |
Description
タナカ氏が HW アールの果樹園を残して亡くなりました。果樹園は東西南北方向に H×W の区画に分けられ、区画ごとにリンゴ、カキ、ミカンが植えられています。タナカ氏はこんな遺言を残していました。
果樹園は区画単位でできるだけ多くの血縁者に分けること。ただし、ある区画の東西南北どれかの方向にとなりあう区画に同じ種類の果物が植えられていた場合は、区画の境界が分からないのでそれらは 1 つの大きな区画として扱うこと。
例えば次のような 3x10 の区画であれば(リはリンゴ、カはカキ、ミはミカンを表す)
同じ樹がある区画の間の境界を消すと次のようになり、
結局 10 個の区画、つまり 10 人で分けられることになります。 雪が降って区画の境界が見えなくなる前に分配を終えなくてはなりません。あなたの仕事は果樹園の地図を もとに分配する区画の数を決めることです。ということで、果樹園の地図を読み込み、分配を受けら れる血縁者の人数を出力して終了するプログラムを作成してください。ただし、果樹園の地図は W 文字×H 行の文字列として与えられます。この文字列には、リンゴを表す@、カキを表す#、ミカンを表す*、の 3 文字しか使われていません。
複数のデータセットが与えられます。各データセットは空白で区切られたH Wを含む行から始まり、続いてH × Wの文字が与えられます。入力はゼロが2つの行で終わります。
H, W は100以下です。
各データセットごとに、分配を受ける人数を1行に出力してください。
10 10 ####*****@ @#@@@@#*#* @##***@@@* #****#*@** ##@*#@@*## *@@@@*@@@# ***#@*@##* *@@@*@@##@ *@*#*@##** @****#@@#@ 0 0
33
Source
思路:
原题是日文版的,中文题意是:
在H * W的矩形果园里有苹果、梨、蜜柑三种果树, 相邻(上下左右)的同种果树属于同一个区域,给出果园的果树分布,求总共有多少个区域。 (原题的样图中苹果为リ,梨为カ,蜜柑为ミ, 图中共10个区域)
输入:
多组数据,每组数据第一行为两个整数H,W(H <= 100, W <= 100), H =0 且 W = 0代表输入结束。以下H行W列表示果园的果树分布, 苹果是@,梨是#, 蜜柑是*。
输出:
对于每组数据,输出其区域的个数。
解题思路是对未搜索过的每个点进行神搜,搜索过的位置置为‘X’,在最上层函数中进行计数。
代码:
#include <iostream> #include <cstdio> using namespace std; #define N 100 int n, m; char tile[N][N+1]; int number; void dfs(int x, int y, char c) { tile[x][y] = 'X'; int d[4][2] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}}; for (int i = 0; i < 4; i ++) { int nx = x + d[i][0], ny = y + d[i][1]; if (0 <= nx && nx < n && 0 <= ny && ny < m && tile[nx][ny] == c) { dfs(nx, ny, c); } } } void solve() { int res = 0; for (int i=0; i<n; i++) { for (int j=0; j<m; j++) { if (tile[i][j] != 'X') { dfs(i, j, tile[i][j]); res ++; } } } printf("%d\n", res); } int main(void) { while (cin >> n >> m) { if (!m && !n) break; for (int i=0; i<n; i++) { cin >> tile[i]; } solve(); } return 0; }
Time Limit: 1000MS | Memory Limit: 65536KB | 64bit IO Format: %lld & %llu |
Description
図のように二股に分かれている容器があります。1 から10 までの番号が付けられた10 個の玉を容器の開口部 A から落とし、左の筒 B か右の筒 C に玉を入れます。板 D は支点 E を中心に左右に回転できるので、板 D を動かすことで筒 B と筒 C のどちらに入れるか決めることができます。開口部 A から落とす玉の並びを与えます。それらを順番に筒 B 又は筒 Cに入れていきます。このとき、筒 B と筒 C のおのおのが両方とも番号の小さい玉の上に大きい玉を並べられる場合は YES、並べられない場合は NO と半角大文字で出力して終了するプログラムを作成してください。ただし、容器の中で玉の順序を入れ替えることはできないものとします。また、続けて同じ筒に入れることができるものとし、筒 B, C ともに10 個の玉がすべて入るだけの余裕があるとします。
複数のデータセットが与えられます。1行目にデータセット数 N が与えられます。つづいて、N 行のデータセットが与えられます。各データセットに 10 個の番号が与えられます。左から1番目の玉の番号、2番目の玉の番号、、、といった順番です。
各データセットに対して、YES または NO を出力して下さい。
2 3 1 4 2 5 6 7 8 9 10 10 9 8 7 6 5 4 3 2 1
YES NO
Source
思路:
有一个形似央视大楼的筒,从A口可以放球,放进去的球可通过挡板DE使其掉进B管或C管里,现有带1-10标号的球按给定顺序从A口放入,问是否有一种控制挡板的策略可以使B管和C管中的球从下往上标号递增。
输入:
用穷举或者DFS搜索都可以。我这里用了代码相对简单的枚举。位运算能够降低存储。
代码:
#include <iostream> #include <cstdio> using namespace std; const int N = 10; int a[N]; void input() { for (int i = 0; i < N; i ++) { scanf("%d", &a[i]); } } void solve() { bool res = false; for (int k = 0; k < (1<<10); k++) { int num = 0; int i; for (i = 0; i < N; i ++) { if ( (1 << i)&k ) { if (a[i] > num) num = a[i]; else break; } } if (i < N) continue; num = 0; for (i = 0; i < N; i ++) { if ( ((1 << i)&k) == 0 ) { if (a[i] > num) num = a[i]; else break; } } if (i == N) { res = true; //printf("k=%d\n", k); break; } } if (res) printf("YES\n"); else printf("NO\n"); } int main(void) { int t; cin >> t; while (t--) { input(); solve(); } return 0; }
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 15450 | Accepted: 6390 |
Description
On Planet MM-21, after their Olympic games this year, curling is getting popular. But the rules are somewhat different from ours. The game is played on an ice game board on which a square mesh is marked. They use only a single stone. The purpose of the game is to lead the stone from the start to the goal with the minimum number of moves.
Fig. 1 shows an example of a game board. Some squares may be occupied with blocks. There are two special squares namely the start and the goal, which are not occupied with blocks. (These two squares are distinct.) Once the stone begins to move, it will proceed until it hits a block. In order to bring the stone to the goal, you may have to stop the stone by hitting it against a block, and throw again.
Fig. 1: Example of board (S: start, G: goal)
The movement of the stone obeys the following rules:
Under the rules, we would like to know whether the stone at the start can reach the goal and, if yes, the minimum number of moves required.
With the initial configuration shown in Fig. 1, 4 moves are required to bring the stone from the start to the goal. The route is shown in Fig. 3(a). Notice when the stone reaches the goal, the board configuration has changed as in Fig. 3(b).
Fig. 3: The solution for Fig. D-1 and the final board configuration
Input
The input is a sequence of datasets. The end of the input is indicated by a line containing two zeros separated by a space. The number of datasets never exceeds 100.
Each dataset is formatted as follows.
the width(=w) and the height(=h) of the board
First row of the board
...
h-th row of the board
The width and the height of the board satisfy: 2 <= w <= 20, 1 <= h <= 20.
Each line consists of w decimal numbers delimited by a space. The number describes the status of the corresponding square.
0 vacant square 1 block 2 start position 3 goal position
The dataset for Fig. D-1 is as follows:
6 6
1 0 0 2 1 0
1 1 0 0 0 0
0 0 0 0 0 3
0 0 0 0 0 0
1 0 0 0 0 1
0 1 1 1 1 1
Output
For each dataset, print a line having a decimal integer indicating the minimum number of moves along a route from the start to the goal. If there are no such routes, print -1 instead. Each line should not have any character other than this number.
Sample Input
2 1 3 2 6 6 1 0 0 2 1 0 1 1 0 0 0 0 0 0 0 0 0 3 0 0 0 0 0 0 1 0 0 0 0 1 0 1 1 1 1 1 6 1 1 1 2 1 1 3 6 1 1 0 2 1 1 3 12 1 2 0 1 1 1 1 1 1 1 1 1 3 13 1 2 0 1 1 1 1 1 1 1 1 1 1 3 0 0
Sample Output
1 4 -1 4 10 -1
Source
思路:
题意是:已知起点和终点,求石子从起点到达终点的最短路,如果无法到达,则输出-1。
石子移动的具体规则如下:
1、开始时,石子在起点s处
2、运动方向可以是水平或垂直的,不能斜方向运动
3、最开始的时候,你可以将石子向上下左右任意一个方向抛,如果与它相邻的点是障碍物的话除外
4、一旦石子开始运动,有三种可能:
a、遇到障碍物,石子会停在障碍物的前一格,障碍物会消失
b、如果出界,游戏失败
c、到达终点,游戏结束并成功
5、如果移动的次数超过10次,将认为游戏是失败的
图中各方格的标示为:
0代表无障碍;
1有障碍;
2为起点;
3为终点。
需要注意的几个地方:
1、石子碰到障碍物时障碍物会消失。也就是说每走一步图的状态都会发生改变,这导致BFS无法成功。
2、移动次数10次实际上是帮助剪枝的,最小步数也可帮助剪枝。
解法:
所以比较合适的解法是DFS,DFS前要对障碍物1更新为0,结束后更改回来。即此题的解法为DFS+回溯。
代码:
Source Code Problem: 3009 User: liangrx06 Memory: 236K Time: 32MS Language: C++ Result: Accepted Source Code #include <iostream> #include <cstdio> using namespace std; #define N 20 #define MAX_STEP 10 int n, m; int map[N][N]; int minStep; bool legal(int x, int y) { return 0 <= x && x < n && 0 <= y && y < m; } void dfs(int x, int y, int step) { if (step >= MAX_STEP || step >= minStep) return; int d[4][2] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}}; for (int i = 0; i < 4; i ++) { int nx = x + d[i][0], ny = y + d[i][1]; if (!legal(nx, ny) || map[nx][ny] == 1) continue; if (map[nx][ny] == 3) { minStep = step + 1; continue; } while (true) { nx += d[i][0], ny += d[i][1]; if (!legal(nx, ny)) break; else if (map[nx][ny] == 1) { map[nx][ny] = 0; dfs(nx-d[i][0], ny-d[i][1], step+1); map[nx][ny] = 1; break; } else if (map[nx][ny] == 3) { minStep = step + 1; break; } } } } void solve() { int bx, by; for (int i=0; i<n; i++) { for (int j=0; j<m; j++) { if (map[i][j] == 2) { bx = i; by = j; } } } minStep = MAX_STEP + 1; dfs(bx, by, 0); if (minStep <= MAX_STEP) printf("%d\n", minStep); else printf("%d\n", -1); } int main(void) { while (cin >> m >> n) { if (!m && !n) break; for (int i=0; i<n; i++) { for (int j=0; j<m; j++) { scanf("%d", &map[i][j]); } } solve(); } return 0; }