题目:
链接:登录—专业IT笔试面试备考平台_牛客网
bfs版:
#include<bits/stdc++.h>
using namespace std;
int m,se=0;
char mas[10][110];
bool vis[10][110]={0};
int cnt1=0,cnt[500]={0},ans=0;
int dir[][4]={{1,0},{-1,0},{0,1},{0,-1},{1,1},{-1,-1},{1,-1},{-1,1}};
inline void bfs(int X,int Y){
queue<pair<int,int> >s;
s.push(make_pair(X,Y));
vis[X][Y]=1;
while(!s.empty()){
int x=s.front().first,y=s.front().second;s.pop();
for(int i=0;i<8;++i){
int xx=x+dir[i][0],yy=y+dir[i][1];
if(xx&&xx<=4&&yy&&yy<=m){
if(!vis[xx][yy]&&mas[xx][yy]=='*'){
vis[xx][yy]=1;s.push(make_pair(xx,yy));
}
}
}
}
}
inline int bf2(int X,int Y){
queue<pair<int,int> >s;
s.push(make_pair(X,Y));
vis[X][Y]=1;int ans=0;
while(!s.empty()){
int x=s.front().first,y=s.front().second;s.pop();++ans;
for(int i=0;i<8;++i){
int xx=x+dir[i][0],yy=y+dir[i][1];
if(xx>4&&xx<=8&&yy&&yy<=m){
if(!vis[xx][yy]&&mas[xx][yy]=='*'){
vis[xx][yy]=1;s.push(make_pair(xx,yy));
}
}
}
}
return ans;
}
int main()
{
cin>>m;
for(int i=1;i<=8;++i){
for(int j=1;j<=m;++j) cin>>mas[i][j];
}
for(int i=1;i<=4;++i){//司机大炮
for(int j=1;j<=m;++j){
if(mas[i][j]=='*'&&!vis[i][j]){
bfs(i,j);
++cnt1;
}
}
}
for(int i=5;i<=8;++i){//齐齐的大炮
for(int j=1;j<=m;++j){
if(mas[i][j]=='*'&&!vis[i][j]){
//bfs2(i,j);
cnt[++cnt[0]]=bf2(i,j);
}
}
}
if(cnt[0]<cnt1){
cout<<-1<<endl;
return 0;
}
sort(cnt+1,cnt+1+cnt[0]);
int sd=0;
for(int i=cnt1;i<=cnt[0];++i){
sd+=cnt[i];
}
cout<<sd<<endl;
return 0;
}
就是分两次搜索,找出所有连通块,齐齐跟司机的连通块永远是一换一(除了最后一轮,齐齐直接把司机打没了),所以一个简单贪心,每次用连通块内大炮数最少的连通块去跟司机极限一换一,最后那些多出来的,就是答案了。
for(int i=5;i<=8;++i){//齐齐的大炮
for(int j=1;j<=m;++j){
if(mas[i][j]=='*'&&!vis[i][j]){
//bfs2(i,j);
cnt[++cnt[0]]=bf2(i,j);
}
}
}
if(cnt[0]<cnt1)
这里的计数方式是我刚学的,cnt[0]用来记录连通块数,cnt[i]记录每个连通块的大炮数。其实也只是少定义了一个sum,但是感觉挺装逼的哈哈哈哈哈。
当然也可以用dfs,思路是一样的。