《挑战程序设计竞赛》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 高斯消元法 * ...
随机推荐
- Linux下中断程序导致写文件失败的分析
案例: 一个普通linux C程序,执行期间会进行多次printf操作,利用bash脚本重定向功能,将stdout重定向到一个另一个文件中去.在运行途中用ctrl+C终止程序,发现定向文件始终为空,即 ...
- jQuery 获取DOM节点的两种方式
jQuery中包裹后的DOM对象实际上是一个数组,要获得纯粹的DOM对象可以有两种方式: 1.使用数组索引方式访问,例如: var dom = $(dom)[0]; 如: $("#id&qu ...
- spring自己主动装配Bean属性
spring提供了3种类型的自己主动装配 byName:把与Bean的属性具有同样名字(或者ID)的其它Bean自己主动装配到Bean的相应属性中. byType:把与Bean的属性具有同样类型的其它 ...
- SSH——基于datagrid实现分页查询
1. 修改页面中datagrid的URL地址,访问action // 取派员信息表格 $('#grid').datagrid( { iconCls : 'icon-forward', fit : tr ...
- SSM&SSH项目中 springmvc 乱码问题解决
需要在web.xml文件中配置过滤器: <!-- 过滤器 过滤乱码 --> <filter> <filter-name>characterEncodingFilte ...
- webpack打包vue2.0项目时必现问题(转载)
原文地址:http://www.imooc.com/article/17868 [Vue warn]: You are using the runtime-only build of Vue wher ...
- 非常酷的 Javascript 简单调试工具Blackbird
Blackbird 是一个开源的 Javascript 调试工具,默认提供一种非常酷的方式展现 Javascript 调试信息,如下图,效果如何呢? 在我们的日常的学习或工作中,经常都会接触到 Jav ...
- 20181011_matplotlib
import numpy as np import pandas as pd import matplotlib.pyplot as plt df=pd.DataFrame(np.random.ran ...
- vue 跨域:使用vue-cli 配置 proxyTable 实现跨域问题
路径在/config/index.js 中,找到dev.proxyTable.如下配置示例: proxyTable: { '/api': { // 我要请求的地址 target: 'http://oa ...
- Centos7 卸载rpm包、卸载yum安装的包
1. 通过rpm -q <关键字>查到rpm包的名字.2. 调用rpm -e <包名>删除特定的rpm包