《挑战程序设计竞赛》2.1 深度优先搜索 POJ2386 POJ1979 AOJ0118 AOJ0033 POJ3009
POJ2386
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 25366 | Accepted: 12778 |
Description
out how many ponds have formed in his field. A pond is a connected set of squares with water in them, where a square is considered adjacent to all eight of its neighbors.
Given a diagram of Farmer John's field, determine how many ponds he has.
Input
* Lines 2..N+1: M characters per line representing one row of Farmer John's field. Each character is either 'W' or '.'. The characters do not have spaces between them.
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
There are three ponds: one in the upper left, one in the lower left,and one along the right side.
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;
}
POJ1979
Time Limit: 1000MS | Memory Limit: 30000K | |
Total Submissions: 27075 | Accepted: 14714 |
Description
Write a program to count the number of black tiles which he can reach by repeating the moves described above.
Input
There are H more lines in the data set, each of which includes W characters. Each character represents the color of a tile as follows.
'.' - a black tile
'#' - a red tile
'@' - a man on a black tile(appears exactly once in a data set)
The end of the input is indicated by a line consisting of two zeros.
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;
}
AOJ0118
Time Limit: 1000MS | Memory Limit: 65536KB | 64bit IO Format: %lld & %llu |
Description
タナカ氏が HW アールの果樹園を残して亡くなりました。果樹園は東西南北方向に H×W の区画に分けられ、区画ごとにリンゴ、カキ、ミカンが植えられています。タナカ氏はこんな遺言を残していました。
果樹園は区画単位でできるだけ多くの血縁者に分けること。ただし、ある区画の東西南北どれかの方向にとなりあう区画に同じ種類の果物が植えられていた場合は、区画の境界が分からないのでそれらは 1 つの大きな区画として扱うこと。
例えば次のような 3x10 の区画であれば(リはリンゴ、カはカキ、ミはミカンを表す)
同じ樹がある区画の間の境界を消すと次のようになり、
結局 10 個の区画、つまり 10 人で分けられることになります。 雪が降って区画の境界が見えなくなる前に分配を終えなくてはなりません。あなたの仕事は果樹園の地図を もとに分配する区画の数を決めることです。ということで、果樹園の地図を読み込み、分配を受けら れる血縁者の人数を出力して終了するプログラムを作成してください。ただし、果樹園の地図は W 文字×H 行の文字列として与えられます。この文字列には、リンゴを表す@、カキを表す#、ミカンを表す*、の 3 文字しか使われていません。
Input
複数のデータセットが与えられます。各データセットは空白で区切られたH Wを含む行から始まり、続いてH × Wの文字が与えられます。入力はゼロが2つの行で終わります。
H, W は100以下です。
Output
各データセットごとに、分配を受ける人数を1行に出力してください。
Sample Input
10 10
####*****@
@#@@@@#*#*
@##***@@@*
#****#*@**
##@*#@@*##
*@@@@*@@@#
***#@*@##*
*@@@*@@##@
*@*#*@##**
@****#@@#@
0 0
Output for the Sample Input
33
Source
(extended version)
http://www.pref.fukushima.jp/pc-concours/
思路:
原题是日文版的,中文题意是:
在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;
}
AOJ0033
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 個の玉がすべて入るだけの余裕があるとします。
Input
複数のデータセットが与えられます。1行目にデータセット数 N が与えられます。つづいて、N 行のデータセットが与えられます。各データセットに 10 個の番号が与えられます。左から1番目の玉の番号、2番目の玉の番号、、、といった順番です。
Output
各データセットに対して、YES または NO を出力して下さい。
Sample Input
2
3 1 4 2 5 6 7 8 9 10
10 9 8 7 6 5 4 3 2 1
Output for the Sample Input
YES
NO
Source
http://www.pref.fukushima.jp/pc-concours/
思路:
有一个形似央视大楼的筒,从A口可以放球,放进去的球可通过挡板DE使其掉进B管或C管里,现有带1-10标号的球按给定顺序从A口放入,问是否有一种控制挡板的策略可以使B管和C管中的球从下往上标号递增。
输入:
第一行输入数据组数N。接下来N行为N组具体数据,每组数据中有10个整数,代表球的放入顺序。
输出:
对于每组数据,若策略存在,输出YES;若不存在,输出NO。
用穷举或者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;
}
POJ3009
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:
- At the beginning, the stone stands still at the start square.
- The movements of the stone are restricted to x and y directions. Diagonal moves are prohibited.
- When the stone stands still, you can make it moving by throwing it. You may throw it to any direction unless it is blocked immediately(Fig. 2(a)).
- Once thrown, the stone keeps moving to the same direction until one of the following occurs:
- The stone hits a block (Fig. 2(b), (c)).
- The stone stops at the square next to the block it hit.
- The block disappears.
- The stone gets out of the board.
- The game ends in failure.
- The stone reaches the goal square.
- The stone stops there and the game ends in success.
- The stone hits a block (Fig. 2(b), (c)).
- You cannot throw the stone more than 10 times in a game. If the stone does not reach the goal in 10 moves, the game ends in failure.
Fig. 2: Stone movements
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;
}
《挑战程序设计竞赛》2.1 深度优先搜索 POJ2386 POJ1979 AOJ0118 AOJ0033 POJ3009的更多相关文章
- Aizu 2249Road Construction 单源最短路变形《挑战程序设计竞赛》模板题
King Mercer is the king of ACM kingdom. There are one capital and some cities in his kingdom. Amazin ...
- 《挑战程序设计竞赛》2.3 动态规划-优化递推 POJ1742 3046 3181
POJ1742 http://poj.org/problem?id=1742 题意 有n种面额的硬币,面额个数分别为Ai.Ci,求最多能搭配出几种不超过m的金额? 思路 据说这是传说中的男人8题呢,对 ...
- 挑战程序设计竞赛》P345 观看计划
<挑战程序设计竞赛>P345 观看计划 题意:一周一共有M个单位的时间.一共有N部动画在每周si时 ...
- POJ 2386 Lake Counting 题解《挑战程序设计竞赛》
地址 http://poj.org/problem?id=2386 <挑战程序设计竞赛>习题 题目描述Description Due to recent rains, water has ...
- poj 3253 Fence Repair 贪心 最小堆 题解《挑战程序设计竞赛》
地址 http://poj.org/problem?id=3253 题解 本题是<挑战程序设计>一书的例题 根据树中描述 所有切割的代价 可以形成一颗二叉树 而最后的代价总和是与子节点和深 ...
- 《挑战程序设计竞赛》——DFS
DFS(深度优先搜索) 简介 深度优先搜索(DFS,Depth-First Search)是搜索的手段之一.它从某个状态开始,不断的转移状态直到无法转移.然后退回到前一步的状态,继续转移到其他状态,如 ...
- 《挑战程序设计竞赛》2.1 穷竭搜索 POJ2718 POJ3187 POJ3050 AOJ0525
POJ2718 Smallest Difference Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 6509 Acce ...
- 《挑战程序设计竞赛》2.1 广度优先搜索 AOJ0558 POJ3669 AOJ0121
AOJ0558 原文链接: AOJ0558 题意: 在H * W的地图上有N个奶酪工厂,分别生产硬度为1-N的奶酪.有一只吃货老鼠准备从老鼠洞出发吃遍每一个工厂的奶酪.老鼠有一个体力值,初始时为1,每 ...
- 《挑战程序设计竞赛》 4.1.1 矩阵 P286
想写几篇挑战的感悟,也有助于自己理解这本书.但这上面大多贴的是书上的代码,主要是为了用的时候后直接复制就好了,这样就很方便了,就相当于黑盒模板了. 1.线性方程组 /** \brief 高斯消元法 * ...
随机推荐
- undefined reference to `std::cout'等错误
(1)gcc和g++都是GNU(组织)的一个编译器. (2)后缀名为.c的程序和.cpp的程序g++都会当成是c++的源程序来处理.而gcc不然,gcc会把.c的程序处理成c程序. (3)对于.cpp ...
- SSH——基于datagrid实现分页查询
1. 修改页面中datagrid的URL地址,访问action // 取派员信息表格 $('#grid').datagrid( { iconCls : 'icon-forward', fit : tr ...
- select/poll/epoll原理探究及总结
select,poll,epoll都是IO多路复用的机制.I/O多路复用就通过一种机制,可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作.但select ...
- sql 多线程
1.codeproject上面一个多线程执行sql的库. 开发中常常要执行一些耗时的数据操作,比如update.insert.bulk insert.index creation, 若顺序执行,则操作 ...
- linux后台运行命令
Ctrl+z/bg/nohup/setsid/& screen 区别待续
- Predix中模型设计
GE的Predix使用了图形数据库作为Asset存储,用以解决传统RDBMS系统中扩展性差,不支持行的动态定义问题. 对于实体,或者Asset来说,由如下几个方面表述: ID: Ties everyt ...
- 记一次elementUI Icon 加载无效的问题。并且提示错误 Failed to decode downloaded font:
问题在于webpack的loader中.检查了一下发现有两个相同的file-loader的配置,删除其中一个即可.
- silverlight RadGridView总结三(转载)
在RadGridView中进行分组以及导出 分组 主要是在前台进行分组的定义: 前台代码: <telerik:RadGridView x:Name="RadGridView1" ...
- [JavaSecurity] - AES Encryption
1. AES Algorithm The Advanced Encryption Standard (AES), also as known as Rijndael (its original nam ...
- C++ regex
我TM看了很久的文档,还是无法理解为什么我用MinGW GCC 4.8.1编译的C++11 <regex>总是抛出异常:regex_error 还是下载boost regex吧 或者c语言 ...