P8662 [蓝桥杯 2018 省 AB] 全球变暖
题目描述
你有一张某海域 N×N 像素的照片,.
表示海洋、 #
表示陆地,如下所示:
.......
.##....
.##....
....##.
..####.
...###.
.......
其中 "上下左右" 四个方向上连在一起的一片陆地组成一座岛屿。例如上图就有 22 座岛屿。
由于全球变暖导致了海面上升,科学家预测未来几十年,岛屿边缘一个像素的范围会被海水淹没。具体来说如果一块陆地像素与海洋相邻(上下左右四个相邻像素中有海洋),它就会被淹没。
例如上图中的海域未来会变成如下样子:
.......
.......
.......
.......
....#..
.......
.......
请你计算:依照科学家的预测,照片中有多少岛屿会被完全淹没。
输入格式
第一行包含一个整数 N.(1≤N≤1000)。
以下 N 行 N 列代表一张海域照片。
照片保证第 11 行、第 11 列、第 N 行、第 N 列的像素都是海洋。
输出格式
一个整数表示答案。
输入输出样例
输入 #1复制
7 ....... .##.... .##.... ....##. ..####. ...###. .......
输出 #1复制
1
说明/提示
时限 1 秒, 256M。蓝桥杯 2018 年第九届省赛
这个题说明一下,先进行一遍dfs统计总数的岛屿,只需把周围是海洋的陆地覆盖一下,剩下的陆地就是还没完全淹没的岛屿,还有连在一起的陆地就是一个岛屿了,当时一直纠结上下左右连在一块的是岛屿,还有考虑的地方是把每个岛屿用另外一个字符围起来,表示它是单独的岛屿(去重)避免算到同一个岛屿上去。废话不多说,上代码。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int next[4][2]={0,1,
1,0,
0,-1,
-1,0
};
char a[1005][1005],b[1005][1005];
book[1005][1005];
int n;
int summ;
void dfs(int x,int y,int num)//海洋覆盖一个单位
{ if(num==1)
{b[x][y]='.';
for(int i=0;i<4;i++)
{
int tx,ty;
tx=x+next[i][0];
ty=y+next[i][1];
if(tx<0||ty<0||tx>n-1||ty>n-1)
continue;
if(b[tx][ty]=='#')
{
dfs(tx,ty,num);
}
}
}
else
{
a[x][y]='.';
for(int i=0;i<4;i++)
{
int tx,ty;
tx=x+next[i][0];
ty=y+next[i][1];
if(tx<0||ty<0||tx>n-1||ty>n-1)
continue;
if(a[tx][ty]!='.')
{
dfs(tx,ty,num);
}
}
}
}
int pd(int x,int y)
{
for(int i=0;i<4;i++)//判断周围是否有海洋
{
int tx,ty;
tx=x+next[i][0];
ty=y+next[i][1];
if(a[tx][ty]=='.')
return 1;
}
return 0;
}
int main()
{
int sum=0;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%s",a[i]);
strcpy(b[i],a[i]);
}
for(int i=0;i<n;i++)//对所有的岛屿进行统计
{
for(int j=0;j<n;j++)
{
if(b[i][j]=='#')
{ summ++;
dfs(i,j,1);
}
}
}
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
if(a[i][j]=='#')对没个岛屿的周围用另外一个字符代替
{
if(pd(i,j))
a[i][j]='|';
}
}
}
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
if(a[i][j]=='#')//对没有淹没的到进行计数
{
sum++;
dfs(i,j,0);
}
}
}
// for(int i=0;i<n;i++)
// printf("%s\n",a[i]);
printf("%d",summ-sum);
return 0;
}
P8673 [蓝桥杯 2018 国 C] 迷宫与陷阱
题目描述
小明在玩一款迷宫游戏,在游戏中他要控制自己的角色离开一间由 N×N 个格子组成的二维迷宫。
小明的起始位置在左上角,他需要到达右下角的格子才能离开迷宫。
每一步,他可以移动到上下左右相邻的格子中(前提是目标格子可以经过)。
迷宫中有些格子小明可以经过,我们用 .
表示;
有些格子是墙壁,小明不能经过,我们用 #
表示。
此外,有些格子上有陷阱,我们用 X
表示。除非小明处于无敌状态,否则不能经过。
有些格子上有无敌道具,我们用 %
表示。
当小明第一次到达该格子时,自动获得无敌状态,无敌状态会持续 K 步。
之后如果再次到达该格子不会获得无敌状态了。
处于无敌状态时,可以经过有陷阱的格子,但是不会拆除 / 毁坏陷阱,即陷阱仍会阻止没有无敌状态的角色经过。
给定迷宫,请你计算小明最少经过几步可以离开迷宫。
输入格式
第一行包含两个整数 �N 和 �K。(1≤N≤1000,1≤K≤10)。
以下 N 行包含一个N×N 的矩阵。
矩阵保证左上角和右下角是 .
。
输出格式
一个整数表示答案。如果小明不能离开迷宫,输出 −1−1。
输入输出样例
输入 #1复制
5 3 ...XX ##%#. ...#. .###. .....
输出 #1复制
10
输入 #2复制
5 1 ...XX ##%#. ...#. .###. .....
输出 #2复制
12
说明/提示
时限 3 秒, 256M。蓝桥杯 2018 年第九届国赛
这是一道bfs模版题,与其他不同的是,如何处理道具的问题,我们看看代码如何实现。
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
struct note
{
int x,y;
int step,wd;
}que[10001000];
char a[1005][1005];
int vis[1005][1005];
int n,k;
int now;
int next1[4][2]={0,1,
1,0,
0,-1,
-1,0
};
int main()
{
memset(vis,-1,sizeof(vis));
int head,tail;
head=tail=0;
que[tail].x=1;
que[tail].y=1;
que[tail].step=0;
tail++;
cin>>n>>k;
for(int i=1;i<=n;i++)
cin>>a[i]+1;
while(head<tail)
{
for(int i=0;i<4;i++)
{
int tx,ty;
tx=que[head].x+next1[i][0];
ty=que[head].y+next1[i][1];
if(tx==n&&ty==n)
{
cout<<que[head].step+1;
return 0;
}
if(tx<1||ty<1||tx>n||ty>n)
continue;
if(a[tx][ty]=='X'&&que[head].wd==0)
continue;
now=0>que[head].wd-1?0:que[head].wd-1;
if(a[tx][ty]=='%')
{
now=k;
}
if(a[tx][ty]!='#'&&vis[tx][ty]<now)
{ vis[tx][ty]=now;
que[tail].x=tx;
que[tail].y=ty;
que[tail].step=que[head].step+1;
que[tail].wd=now;
tail++;
}
}
head++;
}
cout<<-1;
return 0;
}
P3370 【模板】字符串哈希
题目描述
如题,给定 N 个字符串(第 i 个字符串长度为 Mi,字符串内包含数字、大小写字母,大小写敏感),请求出 N 个字符串中共有多少个不同的字符串。
友情提醒:如果真的想好好练习哈希的话,请自觉。
输入格式
第一行包含一个整数 N,为字符串的个数。
接下来 N 行每行包含一个字符串,为所提供的字符串。
输出格式
输出包含一行,包含一个整数,为不同的字符串个数。
输入输出样例
输入 #1复制
5 abc aaaa abc abcc 12345
输出 #1复制
4
说明/提示
对于 30%30% 的数据:N≤10,Mi≈6,Mmax≤15。
对于 70%70% 的数据N≤1000,Mi≈100,Mmax≤150。
对于 100%100% 的数据:N≤10000,Mi≈1000,����≤1500Mmax≤1500。
样例说明:
样例中第一个字符串(abc)和第三个字符串(abc)是一样的,所以所提供字符串的集合为{aaaa,abc,abcc,12345},故共计4个不同的字符串。
这是一道哈希表的模拟题,之前我们说了哈希表的功能是检索速度非常快的一种数据结构,但是它也有缺点,就比如所orzc的哈希值是233,而orzhjw的哈希值也是233,这种情况称为哈希冲突,为了解决哈希冲突,有许多方法,比如拉链法,开放地址法等等,我们这里用进制哈希来解决这种问题,首先我们先定义个进制数base,然后对字符串进行运算。看看代码吧。
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
char a[1505];
long long hash_[10005];
int n;
int base=19;
unsigned long long Hash(char *s)
{
int len=strlen(s);
unsigned long long sum=0;
for(int i=0;i<len;i++)
{
sum=base*sum+(unsigned long long)+s[i];//这里进行了数据的溢出,太玄学了
}
return sum;
}
int main()
{
int m;
cin>>n;
m=n;
for(int i=0;i<m;i++)
{
cin>>a;
hash_[i]=Hash(a);
//cout<<mod(len)<<' ';
}
sort(hash_,hash_+n);
long long ans=0;
for(int i=0;i<n-1;i++)
{
if(hash_[i]!=hash_[i+1])
ans++;
}
cout << ans+1 << endl;
return 0;
}