AcWing 687. 扫雷
模拟以下样例(10X10):
把扫雷地图转变为数字记录的地图:地雷记作-1,其余表示8个方向有几个地雷,完成后如下图:
接着搜索所有0联通块(为红色矩形),并且把联通块附近不是地雷的点(红色圆形)全标记为-1,如下图:
而答案就是当前该图中大于0的数的数目之和,再加上原来0联通块的数目,dfs(AC):
cpp
#include<iostream>
#include<cstring>
using namespace std;
const int N=305;
int T,n;
char a[N][N]; //原地图
int b[N][N]; //数字地图
bool flag[N][N];//标记数组
int dx[8]={-1,-1,0,1,1,1,0,-1};
int dy[8]={0,1,1,1,0,-1,-1,-1};
void dfs(int x,int y){
if(b[x][y]>0) {b[x][y]=-1;return;}
for(int i=0;i<8;i++){
int xx=x+dx[i],yy=y+dy[i];
if(xx>=1&&xx<=n&&yy>=1&&yy<=n){
if(!flag[xx][yy]){
flag[xx][yy]=1;
if(b[xx][yy]>=0){
dfs(xx,yy);
}
}
}
}
}
int main(){
cin>>T;
for(int i=1;i<=T;i++){
cin>>n;
cout<<"Case #"<<i<<":"<<" ";
//地图转换
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{cin>>a[i][j];if(a[i][j]=='*') b[i][j]=-1;}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(a[i][j]=='.'){
int t=0;
for(int k=0;k<8;k++){
int x=i+dx[k],y=j+dy[k];
if(x>=1&&x<=n&&y>=1&&y<=n&&a[x][y]=='*'){
t++;
}
}
b[i][j]=t;
}
}
}
//各变量初始化
int ans=0;
memset(flag,0,sizeof flag);
//搜索0联通块,并且计算联通块数目
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(!flag[i][j]&&b[i][j]==0) {flag[i][j]=1;dfs(i,j);ans++;}
//计算剩余大于0数的数目,求得答案
for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(b[i][j]>0) ans++;
cout<<ans<<endl;
}
return 0;
}
AcWing 643. 动态网格
模拟+dfs:
cpp
#include<iostream>
#include<cstring>
using namespace std;
const int N=105;
int T,R,C,n;
char a[N][N];
bool flag[N][N];
int dx[4]={-1,0,1,0};
int dy[4]={0,1,0,-1};
void dfs(int x,int y){
flag[x][y]=1;
for(int i=0;i<4;i++){
int xx=x+dx[i],yy=y+dy[i];
if(xx>=0&&xx<R&&yy>=0&&yy<C){
if(a[xx][yy]=='1'&&flag[xx][yy]==0){
dfs(xx,yy);
}
}
}
return ;
}
int main(){
cin>>T;
for(int k=1;k<=T;k++){
cin>>R>>C;
for(int i=0;i<R;i++) for(int j=0;j<C;j++) cin>>a[i][j];
cin>>n;
cout<<"Case #"<<k<<":"<<endl;
while(n--){
int ans=0;
memset(flag,0,sizeof flag);
char ch;
cin>>ch;
if(ch=='M'){
int x,y,z;
cin>>x>>y>>z;
if(z==1) a[x][y]='1';
else a[x][y]='0';
}
else{
for(int i=0;i<R;i++){
for(int j=0;j<C;j++){
if(a[i][j]=='1'&&flag[i][j]==0){
dfs(i,j);
ans++;
}
}
}
cout<<ans<<endl;
}
}
}
return 0;
}
AcWing 844. 走迷宫
bfs:
cpp
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
const int N=110;
int n,m;
typedef pair<int,int>pii;
int mapp[N][N],d[N][N];
int bfs(){
memset(d,-1,sizeof d);
d[1][1]=0;
queue<pii>q;
q.push({1,1});
int dx[4]={-1,0,1,0},dy[4]={0,1,0,-1};
while(q.size()){
auto t=q.front();
q.pop();
for(int i=0;i<4;i++){
int x=t.first+dx[i],y=t.second+dy[i];
if(x>=1&&x<=n&&y>=1&&y<=m&&d[x][y]==-1&&mapp[x][y]==0){
d[x][y]=d[t.first][t.second]+1;
q.push({x,y});
}
}
}
return d[n][m];
}
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) cin>>mapp[i][j];
cout<<bfs()<<endl;
return 0;
}
AcWing 3224. 画图
这题最大的问题就是题目给的坐标不方便,只需要处理好坐标转换,再把两个操作函数写好即可:
cpp
#include<iostream>
#include<cstring>
using namespace std;
const int N=105;
int n,m,q;
int dx[4]={-1,0,1,0};
int dy[4]={0,1,0,-1};
char a[N][N];
bool flag[N][N];
//画线函数
void line(int x1,int y1,int x2,int y2){
if(x1==x2){//同一行
for(int i=y1;i<=y2;i++){
if(a[x1][i]=='|'||a[x1][i]=='+') a[x1][i]='+';
else a[x1][i]='-';
}
}
if(y1==y2){//同一列
for(int i=x1;i<=x2;i++){
if(a[i][y1]=='-'||a[i][y1]=='+') a[i][y1]='+';
else a[i][y1]='|';
}
}
return ;
}
//填充函数
void fills(int x,int y,char c){
flag[x][y]=1;
a[x][y]=c;
for(int i=0;i<4;i++){
int xx=x+dx[i],yy=y+dy[i];
if(xx>=0&&xx<n&&yy>=0&&yy<m){
if(a[xx][yy]!='-'&&a[xx][yy]!='|'&&a[xx][yy]!='+'){
if(flag[xx][yy]==0){
fills(xx,yy,c);
}
}
}
}
return ;
}
int main(){
cin>>m>>n>>q;
for(int i=0;i<n;i++) for(int j=0;j<m;j++) a[i][j]='.';
while(q--){
int t;
cin>>t;
if(t==0){
int x1,y1,x2,y2;//x和y反着读入
cin>>y1>>x1>>y2>>x2;
if(x1>x2) swap(x1,x2);
if(y1>y2) swap(y1,y2);
line(x1,y1,x2,y2);
}
else{
int x,y;char c;
cin>>y>>x>>c;//x和y反着读入
memset(flag,0,sizeof flag);
fills(x,y,c);
}
}
for(int i=n-1;i>=0;i--){
for(int j=0;j<m;j++){
cout<<a[i][j];
}
cout<<endl;
}
return 0;
}