寒假预备役学习第二天

今天主要在写洛谷团队中的题目,对于搜索这类的题目有了能够解决问题的能力,但是单靠之前学过的东西来完成这些题目依旧较为困难,每一道题用的时间都比较长,部分无法完成的题目我会选择去看视频讲解,有时会出现一些没有学过、甚至没有见过的内容,但通过花时间学习过后也能简单的使用。

P1162 填涂颜色

题目描述

由数字 00 组成的方阵中,有一任意形状的由数字 11 构成的闭合圈。现要求把闭合圈内的所有空间都填写成 22。例如:6×66×6 的方阵(�=6n=6),涂色前和涂色后的方阵如下:

如果从某个 00 出发,只向上下左右 44 个方向移动且仅经过其他 00 的情况下,无法到达方阵的边界,就认为这个 00 在闭合圈内。闭合圈不一定是环形的,可以是任意形状,但保证闭合圈内的 00 是连通的(两两之间可以相互到达)。

0 0 0 0 0 0
0 0 0 1 1 1
0 1 1 0 0 1
1 1 0 0 0 1
1 0 0 1 0 1
1 1 1 1 1 1
0 0 0 0 0 0
0 0 0 1 1 1
0 1 1 2 2 1
1 1 2 2 2 1
1 2 2 1 2 1
1 1 1 1 1 1

输入格式

每组测试数据第一行一个整数 �(1≤�≤30)n(1≤n≤30)。

接下来 �n 行,由 00 和 11 组成的 �×�n×n 的方阵。

方阵内只有一个闭合圈,圈内至少有一个 00。

输出格式

已经填好数字 22 的完整方阵。

输入输出样例

输入 

6
0 0 0 0 0 0
0 0 1 1 1 1
0 1 1 0 0 1
1 1 0 0 0 1
1 0 0 0 0 1
1 1 1 1 1 1

输出 

0 0 0 0 0 0
0 0 1 1 1 1
0 1 1 2 2 1
1 1 2 2 2 1
1 2 2 2 2 1
1 1 1 1 1 1

说明/提示

对于 100%100% 的数据,1≤�≤301≤n≤30。

思路:我们利用两个数组,一个用作地图map,另一个用来记录是否经过,这个题我们采用广搜的方式找出最优解,使用两个队列来完成,x,y分别进栈,只要栈不为空就一直循环下去,这个题依旧需要将可能发生的情况划入数组中(上下左右),值得注意的是,本题需要在判定范围时将周围范围扩大一层,循环结束时将所有经过的且为0的点赋值为2然后打印。

代码:

#include<iostream>
#include<queue>
using namespace std;
int main() {
	int dx[4] = { -1,1,0,0 };
	int dy[4] = { 0,0,-1,1 };
	queue<int>q, q1;
	int n, tx, ty, x, y;
	int a[35][35];
	int v[35][35] = { 0 };
	cin >> n;
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			cin >> a[i][j];
		}
	}
	v[1][1] = 1;
	q.push(1);
	q1.push(1);
	while (!q.empty()){
		x = q.front();
		y = q1.front();
		for (int k = 0; k < 4; k++) {
			tx = x + dx[k];
			ty = y+ dy[k];
			if (tx<0|| tx>n+1||ty<0||ty>n+1)
				continue;
			if (a[tx][ty] == 0 && v[tx][ty] == 0) {
				v[tx][ty] = 1;
				q.push(tx);
				q1.push(ty);
			}
		}
		q.pop();
		q1.pop();
	}
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			if (v[i][j] == 0 && a[i][j] == 0)
				a[i][j] = 2;
		}
	}
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			cout << a[i][j] << " ";
		}
		cout<<endl;
	}
	return 0;
}

P1596 [USACO10OCT] 湖泊计数 S

题目描述

由于最近的降雨,水在农夫约翰的田地里积聚了多个地方,用一个 N x M (1 <= N <= 100; 1 <= M <= 100) 正方形的矩形表示。每个方块包含水(“W”)或旱地(“.”)。农夫约翰想弄清楚他的田地里形成了多少个池塘。池塘是一组相连的方块,里面有水,其中的方块被认为与其所有八个相邻方块相邻。给定农夫约翰的田地图,确定他有多少个池塘。

输入格式

第 1 行:两个空格分隔的整数:N 和 M * 第 2..N+1 行:每行 M 个字符,表示 Farmer John 字段的一行。每个字符都是“W”或“.”。字符之间没有空格。

输出格式

第 1 行:农夫约翰田地里的池塘数量。

题意翻译

由于近期的降雨,雨水汇集在农民约翰的田地不同的地方。 我们用一个 �×�(1≤�≤100,1≤�≤100)N×中号(1≤N≤1 0 0.1≤≤1 0 0) 的网格图表示。 每个网格中有水() 或是旱地()。 一个网格与其周围的八个网格相连,而一组相连的网格视为一个水坑。 约翰想弄清楚他的田地已经形成了多少水坑。 给出约翰田地的示意图,确定当中有多少水坑。W.

输入第 11 行:两个空格隔开的整数:�N 和 �M

第 22 行到第 �+1N+1 行:每行 �M 个字符,每个字符是 或 ,它们表示网格图中的一排。 字符之间没有空格。W.

输出一行,表示水坑的数量。

输入输出样例

输入 
10 12
W........WW.
.WWW.....WWW
....WW...WW.
.........WW.
.........W..
..W......W..
.W.W.....WW.
W.W.W.....W.
.W.W......W.
..W.......W.
输出 
3

说明/提示

输出详细信息:有三个池塘:一个在左上角,一个在左下角,一个在右侧。

思路:  我们需要注意在此题中有八种情况,所有我们要给出八种情况的x,y值并放在数组中,给定一个数组map,我们采用深搜,每当遇到一个‘w'就进行+1,然后将这个点变成'.'表示已经经过,然后再进行搜索,当所有与第一个w相邻的w全部变成’.'后,即可走出一个湖泊,当再遇见w时又是另一个湖泊。

#include<iostream>
using namespace std;
int N, M,sum;
char a[101][101];
void dfs(int x, int y) {
	a[x][y] = '.';
	int dx[8] = { -1,-1,-1,0,0,1,1,1 };
	int dy[8] = { -1,0,1,-1,1,-1,0,1 };
	int tx, ty;
	for (int k = 0; k < 8; k++) {
		tx = x + dx[k];
		ty = y + dy[k];
		if (tx<1 || tx>N || ty<1 || ty>M||a[tx][ty]=='.')
			continue;
		if (a[tx][ty] == 'W')
			a[tx][ty] == '.';
			dfs(tx, ty);
	}
}
int main() {
	sum = 0;
	cin >> N >> M;
	for (int i = 1; i <= N; i++) {
		for (int j = 1; j <= M; j++) {
			cin >> a[i][j];
		}
	}
	for (int i = 1; i <= N; i++) {
		for (int j = 1; j <= M; j++) {
			if (a[i][j] == 'W') {
				dfs(i, j);
				sum++;
			}
			
		}
	}
	cout << sum << endl;
	return 0;
}

P1019 [NOIP2000 提高组] 单词接龙、

对于这个题目我表示真的是毫无头绪,到网上看了相关的讲解视频后发现其中有很多是我没见过,甚至是没学过的东西,只能一点一点去查,从早上到下午花了4、5个小时才搞明白。

看题解前一定要学习一下string相关函数的作用,substr()等

题目背景

注意:本题为上古 NOIP 原题,不保证存在靠谱的做法能通过该数据范围下的所有数据。

本题为搜索题,本题不接受 hack 数据。关于此类题目的详细内容

NOIP2000 提高组 T3

题目描述

单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在两个单词相连时,其重合部分合为一部分,例如 beast 和 astonish,如果接成一条龙则变为 beastonish,另外相邻的两部分不能存在包含关系,例如 at 和 atide 间不能相连。

输入格式

输入的第一行为一个单独的整数 �n 表示单词数,以下 �n 行每行有一个单词,输入的最后一行为一个单个字符,表示“龙”开头的字母。你可以假定以此字母开头的“龙”一定存在。

输出格式

只需输出以此字母开头的最长的“龙”的长度。

输入输出样例

输入 

5
at
touch
cheat
choose
tact
a

输出 

23

说明/提示

样例解释:连成的“龙”为 atoucheatactactouchoose

�≤20n≤20。

思路:本题还是采用两个数组,一个用来记录使用次数,另一个用来存储字符串,在循环中字符串头字符与输入字符相同时进行计数+1,同时进入搜索,但是搜索完之后一定要回溯(计数-1),因为我们在这里使用的是深搜,我们要把所有结果都遍历一遍最后得出最长解,这里要做的是两件事,第一是判断字符串是否包含,第二是连接字符串并返回。

代码:

#include<iostream>
#include<string>
using namespace std;
string ss[25];
int mark[25];
int ans=0,n;
string pd(string s1, string s2) {
	int len1 = s1.length(), len2 = s2.length();
	for (int i = 1; i < len1 && i < len2; i++) {
		if (s1.substr(len1 - i, i) == s2.substr(0, i)) {
			return (s1.substr(0, len1 - i) + s2);
		}
	}
	return "0";
}
void dfs(string drag){
	if (drag.size() > ans)ans = drag.size();
	for (int i = 1; i <= n; i++) {
		if (mark[i] == 2)continue;
		string s = pd(drag, ss[i]);
		if (s != "0") {
			mark[i]++;
			dfs(s);
			mark[i]--;
		}
	}
}
int main() {
	char ch;
	cin >> n;
	for (int i = 1; i <=n; i++) {
		cin >> ss[i];
	}
	cin >> ch;
	for (int i = 1; i <= n; i++) {
		if (ss[i][0] == ch) {
			mark[i]++;
			dfs(ss[i]);
			mark[i]--;
		}
	}
	cout << ans;
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值