4.安排超市
给定一个n*n的地图。地图是上下左右四联通的,不能斜向行走:
*代表障碍,不可通行。
.代表路,可以通行。
#代表房子。房子也是可以通行的。
小红现在需要在一些地方安排一些超市(不能安排在障碍物上,可以安排在路上或者房子上。超市也是可以通行的)。
小红希望每个房子至少可以到达一个超市。同时由于成本原因,小红希望超市的数量尽可能少。
在超市数量最少的情况下,小红希望每个房子到达最近的超市的距离之和尽可能小。
她想知道超市最少的数量,以及最小的距离之和。你能帮帮她吗?
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 256M,其他语言512M
输入描述:
第一行一个正整数n,代表地图的大小。( 1<=n<=50 )
接下来的n行,每行一个长度为n的字符串,表示整个地图。保证输入合法。
输出描述:
输出两个整数,用空格隔开。分别代表超市的最小数量、最小的距离之和。
示例1
输入例子:
3
#.#
.**
.#
输出例子:
2 2
例子说明:
下标从1开始,第一个超市安排的位置是(1,2),第二个超市安排的位置是(3,3)。三个房子到超市的距离分别为1,1,0。
示例2
输入例子:
3
##
.**
.#
输出例子:
3 0
例子说明:
分别在三个房子上建3个超市即可。
示例3
输入例子:
2
.
*.
输出例子:
0 0
例子说明:
没有房子,所以不用造超市
题解
因为保证所有房子都能到达超市,所以先BFS搜索遍历,把整个图分割成几个部分,然后再暴力搜索每个位置造超市去其他房子的距离最小值即可。
AC代码
#include<bits/stdc++.h>
using namespace std;
int n;
string mp[55];
struct Node
{
int x,y,dp;
};
int xx[4] = {0,0,-1,1};
int yy[4] = {-1,1,0,0};
bool vis[55][55];
vector<pair<int, int> > bfs(int x,int y)
{
queue<Node>q;
Node t;
t.x = x, t.y = y;
q.push(t);
vis[x][y] = true;
vector<pair<int, int> >pos;
while(!q.empty())
{
t = q.front();
q.pop();
pos.push_back(pair<int,int>(t.x,t.y));
for(int i=0;i<4;i++)
{
Node w;
w.x = t.x + xx[i];
w.y = t.y + yy[i];
if(w.x<0||w.x>=n||w.y<0||w.y>=n)continue;
if(vis[w.x][w.y])continue;
if(mp[w.x][w.y]=='*')continue;
vis[w.x][w.y] = true;
q.push(w);
}
}
return pos;
}
bool cis[55][55];
int cal_dis(int x,int y)
{
memset(cis,0,sizeof(cis));
queue<Node>q;
Node t;
t.x = x, t.y = y, t.dp=0;
q.push(t);
cis[x][y] = true;
int dis = 0;
while(!q.empty())
{
t = q.front();
q.pop();
if(mp[t.x][t.y]=='#')dis += t.dp;
for(int i=0;i<4;i++)
{
Node w;
w.x = t.x + xx[i];
w.y = t.y + yy[i];
w.dp = t.dp + 1;
if(w.x<0||w.x>=n||w.y<0||w.y>=n)continue;
if(cis[w.x][w.y])continue;
if(mp[w.x][w.y]=='*')continue;
cis[w.x][w.y] = true;
q.push(w);
}
}
return dis;
}
int main()
{
cin>>n;
for(int i=0;i<n;i++)
cin>>mp[i];
memset(vis,0,sizeof(vis));
int num=0, total_dis=0;
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
if(vis[i][j])continue;
if(mp[i][j]=='#')
{
vector<pair<int, int> > pos = bfs(i,j);
int mi_dis = 1e9, dis;
for(int k=0;k<pos.size();k++)
{
// cout<<pos[k].first<<" "<<pos[k].second<<endl;
dis = cal_dis(pos[k].first, pos[k].second);
// cout<<"dis="<<dis<<endl;
mi_dis = min(mi_dis, dis);
}
num++;
total_dis += mi_dis;
//cout<<mi_dis<<endl;
}
}
}
cout<<num<<" "<<total_dis<<endl;
return 0;
}