离开中山路
题目描述
爱与愁大神买完东西后,打算坐车离开中山路。现在爱与愁大神在 x1,y1 处,车站在 x2,y2 处。现在给出一个 n×n(n≤1000) 的地图,0 表示马路,1 表示店铺(不能从店铺穿过),爱与愁大神只能垂直或水平着在马路上行进。爱与愁大神为了节省时间,他要求最短到达目的地距离(每两个相邻坐标间距离为 1)。你能帮他解决吗?
输入格式
第 1 行包含一个数 n。
第 2 行到第 n+1 行:整个地图描述(0 表示马路,1 表示店铺,注意两个数之间没有空格)。
第 n+2 行:四个数 x1,y1,x2,y2。
输出格式
只有 1 行,即最短到达目的地距离。
#include<bits/stdc++.h>
#define fi first
#define se second
#define pb push_back
#define PII pair<int,int >
#define int long long
#define IOS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
using namespace std;
const int N = 1e6+10,M = 2000;
int n,m;
int stx,sty,edx,edy;
char va[M][M];
int vis[M][M];
int dist[M][M];
int dx[4] = {0,0,1,-1};
int dy[4] = {1,-1,0,0};
void bfs()
{
queue<pair<int,int> > q;
vis[stx][sty] = 1;
dist[stx][sty] = 0;
q.push({stx,sty});
while(q.size()>=1)
{
pair<int,int> now = q.front();
q.pop();
int x = now.first,y = now.second;
for(int i=0;i<=3;i++)
{
int xx = x+dx[i],yy = y+dy[i];
if(xx>=1&&xx<=n&&yy>=1&&yy<=n&&vis[xx][yy]==0&&va[xx][yy]=='0')
{
vis[xx][yy] = 1;
dist[xx][yy] = dist[x][y]+1;
q.push({xx,yy});
}
}
}
}
signed main()
{
IOS;
cin>>n;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
cin>>va[i][j];
}
cin>>stx>>sty>>edx>>edy;
bfs();
cout<<dist[edx][edy];
return 0;
}
马的遍历
题目描述
有一个 n×m 的棋盘,在某个点 (x,y) 上有一个马,要求你计算出马到达棋盘上任意一个点最少要走几步。
输入格式
输入只有一行四个整数,分别为 n,m,x,y。
输出格式
一个n×m 的矩阵,代表马到达某个点最少要走几步(不能到达则输出 −1)。
#include<bits/stdc++.h>
#define fi first
#define se second
#define pb push_back
#define PII pair<int,int >
#define int long long
#define IOS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
using namespace std;
const int N = 1e6+10,M = 2000;
int n,m,A,B;
int va[N];
int vis[M][M];
int dist[M][M];
int dx[8] = {-2,-1,1,2,2,1,-1,-2};
int dy[8] = {1,2,2,1,-1,-2,-2,-1};
void bfs()
{
queue<pair<int,int> > q;
dist[A][B] = 0;
vis[A][B] = 1;
q.push({A,B});
while(q.size())
{
auto now = q.front();
q.pop();
int x = now.first,y = now.se;
for(int i=0;i<=7;i++)
{
int xx = x+dx[i],yy = y+dy[i];
if(xx>=1&&xx<=n&&yy>=1&&yy<=m&&vis[xx][yy]==0)
{
vis[xx][yy] = 1;
dist[xx][yy] = dist[x][y]+1;
q.push({xx,yy});
}
}
}
}
signed main()
{
IOS;
cin>>n>>m>>A>>B;
bfs();
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(vis[i][j]==0) printf("%-5d",-1);
else printf("%-5d",dist[i][j]);
}
printf("\n");
}
return 0;
}
奇怪的电梯
题目描述
呵呵,有一天我做了一个梦,梦见了一种很奇怪的电梯。大楼的每一层楼都可以停电梯,而且第 i 层楼(1≤i≤N)上有一个数字 Ki(0≤Ki≤N)。电梯只有四个按钮:开,关,上,下。上下的层数等于当前楼层上的那个数字。当然,如果不能满足要求,相应的按钮就会失灵。例如: 3,3,1,2,53,3,1,2,5 代表了 Ki(K1=3,K2=3,……),从 1楼开始。在 1 楼,按“上”可以到 4 楼,按“下”是不起作用的,因为没有 −2楼。那么,从 A 楼到 B 楼至少要按几次按钮呢?
输入格式
共二行。
第一行为三个用空格隔开的正整数,表示 N,A,B(1≤N≤200,1≤A,B≤N)。
第二行为 N 个用空格隔开的非负整数,表示 Ki。
输出格式
一行,即最少按键次数,若无法到达,则输出 -1
。
#include<bits/stdc++.h>
#define fi first
#define se second
#define pb push_back
#define PII pair<int,int >
#define int long long
#define IOS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
using namespace std;
const int N = 1e6+10,M = 2000;
int n,A,B;
int va[N];
int vis[N];
int dist[N];
void bfs()
{
queue<int > q;
dist[A] = 0;
vis[A] = 1;
q.push(A);
while(q.size())
{
auto now = q.front();
q.pop();
int up = now+va[now],down = now-va[now];
if(up>=1&&up<=n&&vis[up]==0)
{
vis[up] = 1;
dist[up] = dist[now]+1;
q.push(up);
}
if(down>=1&&down<=n&&vis[down]==0)
{
vis[down] = 1;
dist[down] = dist[now]+1;
q.push(down);
}
}
}
signed main()
{
IOS;
cin>>n>>A>>B;
for(int i=1;i<=n;i++) cin>>va[i];
bfs();
if(vis[B]==0) cout<<-1;
else cout<<dist[B];
return 0;
}
Lake Counting S
题意翻译
由于近期的降雨,雨水汇集在农民约翰的田地不同的地方。我们用一N×M(1≤N≤100,1≤M≤100) 的网格图表示。每个网格中有水(W
) 或是旱地(.
)。一个网格与其周围的八个网格相连,而一组相连的网格视为一个水坑。约翰想弄清楚他的田地已经形成了多少水坑。给出约翰田地的示意图,确定当中有多少水坑。
输入第 1 行:两个空格隔开的整数:N 和 M。
第 2 行到第 N+1 行:每行 M 个字符,每个字符是 W
或 .
,它们表示网格图中的一排。字符之间没有空格。
输出一行,表示水坑的数量。
#include<bits/stdc++.h>
#define fi first
#define se second
#define pb push_back
#define PII pair<int,int >
#define int long long
#define IOS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
using namespace std;
const int N = 1e6+10,M = 2000;
int n,m,A,B;
char va[M][M];
int dx[8] = {0,1,1,1,0,-1,-1,-1};
int dy[8] = {1,1,0,-1,-1,-1,0,1};
void bfs(int A,int B)
{
queue<pair<int,int> > q;
va[A][B] = '.';
q.push({A,B});
while(q.size())
{
auto now = q.front();
q.pop();
int x = now.first,y = now.se;
for(int i=0;i<=7;i++)
{
int xx = x+dx[i],yy = y+dy[i];
if(xx>=1&&xx<=n&&yy>=1&&yy<=m&&va[xx][yy]=='W')
{
va[xx][yy] = '.';
q.push({xx,yy});
}
}
}
}
signed main()
{
IOS;
cin>>n>>m;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
cin>>va[i][j];
}
}
int cnt = 0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(va[i][j]=='W')
{
cnt++;
bfs(i,j);
}
}
}
cout<<cnt;
return 0;
}
观星
题目描述
Jimmy 和 Symbol 约好一起看星星,浩瀚的星空可视为一个长为 N、宽为 M 的矩阵,矩阵中共有 N×M 个位置,一个位置可以用坐标 (i,j)(1≤i≤N,1≤j≤M)来表示。每个位置上可能是空的,也可能有一个星星。
对于一个位置 (i,j),与其相邻的位置有左边、左上、上面、右上、右边、右下、下面、左下 8 个位置。相邻位置上的星星被视为同一个星座,这种关系有传递性,例如若 (1,1),(1,2),(1,3)(1,1),(1,2),(1,3) 三个 位置上都有星星,那么这三个星星视为同一个星座。包含的星星数量相同的星座被视为一个星系(一个星系中的星座不一定相邻),星系的大小为星系中包含的所有星星数量。
由于 Symbol 太喜欢星系了,他就想考一考 Jimmy,让 Jimmy 求出星空中有多少个星系,他还想知道,最大的星系有多大。
输入格式
第一行两个整数 N,M 表示矩阵的长宽。
接下来 N 行每行 M 个字符,每个字符只可能是.
或*
。这 N 行中第 i 行的第 j 个字符是*
表示位置 (i,j) 上有一个星星,否则表示它是空的。
输出格式
仅一行两个整数,用空格分隔开,分别表示星系的数量与最大星系的大小。
#include<bits/stdc++.h>
#define fi first
#define se second
#define pb push_back
#define PII pair<int,int >
#define int long long
#define IOS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
using namespace std;
const int N = 1e6+10,M = 2000;
int n,m,A,B;
char va[M][M];
int dx[8] = {0,1,1,1,0,-1,-1,-1};
int dy[8] = {1,1,0,-1,-1,-1,0,1};
map<int,int > mp;
void bfs(int A,int B)
{
queue<pair<int,int> > q;
va[A][B] = '.';
q.push({A,B});
int sum = 0;
while(q.size())
{
auto now = q.front();
q.pop();
sum++;
int x = now.first,y = now.se;
for(int i=0;i<=7;i++)
{
int xx = x+dx[i],yy = y+dy[i];
if(xx>=1&&xx<=n&&yy>=1&&yy<=m&&va[xx][yy]=='*')
{
va[xx][yy] = '.';
q.push({xx,yy});
}
}
}
mp[sum]++;
}
signed main()
{
IOS;
cin>>n>>m;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
cin>>va[i][j];
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(va[i][j]=='*')
{
bfs(i,j);
}
}
}
int maxn = 0;
for(auto t:mp) maxn = max(maxn,t.fi*t.se);
cout<<mp.size()<<" "<<maxn;
return 0;
}
填涂颜色
题目描述
由数字 0 组成的方阵中,有一任意形状的由数字 1 构成的闭合圈。现要求把闭合圈内的所有空间都填写成 2。例如:6×6 的方阵(n=6),涂色前和涂色后的方阵如下:
如果从某个 0 出发,只向上下左右 4 个方向移动且仅经过其他 0 的情况下,无法到达方阵的边界,就认为这个 0 在闭合圈内。闭合圈不一定是环形的,可以是任意形状,但保证闭合圈内的 0 是连通的(两两之间可以相互到达)。
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
输入格式
每组测试数据第一行一个整数 n(1≤n≤30)。
接下来 n 行,由 0 和 1 组成的 n×n 的方阵。
方阵内只有一个闭合圈,圈内至少有一个 0。
输出格式
已经填好数字 2 的完整方阵。
#include<bits/stdc++.h>
#define fi first
#define se second
#define pb push_back
#define PII pair<int,int >
#define int long long
#define IOS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
using namespace std;
const int N = 1e6+10,M = 2000;
int n,m;
int va[M][M];
int dx[4] = {0,0,1,-1};
int dy[4] = {1,-1,0,0};
void bfs(int A,int B)
{
queue<pair<int,int> > q;
if(A==0&&B==0) va[A][B] = -1;
else va[A][B] = 2;
q.push({A,B});
while(q.size())
{
auto now = q.front();
q.pop();
int x = now.fi,y = now.se;
for(int i=0;i<=3;i++)
{
int xx = x+dx[i],yy = y+dy[i];
if(xx>=0&&xx<=n+1&&yy>=0&&yy<=n+1&&va[xx][yy]==0)
{
if(A==0&&B==0) va[xx][yy] = -1;
else va[xx][yy] = 2;
q.push({xx,yy});
}
}
}
}
signed main()
{
IOS;
cin>>n;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
cin>>va[i][j];
}
bfs(0,0);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(va[i][j]==0)
{
bfs(i,j);
}
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(va[i][j]==-1) va[i][j] = 0;
cout<<va[i][j]<<" ";
}
cout<<"\n";
}
return 0;
}