题意:给定一个n*n的方阵,’X’代表墙壁,’.’代表机枪,一个机枪的行列上不可以有其它机枪,除非中间有墙隔着。问给定方阵上最多可以放几个机枪。
思路:贪心+dfs。先统计出所有可以放机枪的点每个如果放了机枪会影响几个区域。然后选取影响最小的防止机枪,然后不断重复操作直到所有区域被覆盖。
#include<bits/stdc++.h>
using namespace std;
const int MAX_N = 10+5;
char maze[MAX_N][MAX_N];
int n,d[MAX_N][MAX_N],dx[4]={0,1,0,-1},dy[4]={-1,0,1,0};
void sol(int t)
{
int x=t/10,y=t%10;
maze[x][y]='S';
for(int i=0;i<4;i++){
for(int c=1;c<=n;c++){
int nx=x+dx[i]*c,ny=y+dy[i]*c;
if(nx>=0&&nx<n&&ny>=0&&ny<n){
if(maze[nx][ny]=='X') break;
else {
maze[nx][ny]='S';
}
}
}
}
}
int sear()
{
int minn=MAX_N,ans=-1;
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(maze[i][j]=='X'||maze[i][j]=='S') continue;
if(d[i][j]<minn){
minn=d[i][j];
ans=i*10+j;
}
}
}
//cout<<maze[ans/10][ans%10]<<' '<<ans<<endl;
return ans;
}
void cacul(int x,int y)
{
int ans=0;
for(int i=0;i<4;i++){
for(int c=1;c<=n;c++){
int nx=x+dx[i]*c,ny=y+dy[i]*c;
if(nx>=0&&nx<n&&ny>=0&&ny<n){
if(maze[nx][ny]=='X') break;
else ans++;
}
}
}
d[x][y]=ans;
//cout<<d[x][y]<<endl;
}
int main()
{
int ans;
while(cin>>n&&n){
ans=0;
for(int i=0;i<n;i++){
scanf("%s",maze[i]);
}
memset(d,-1,sizeof(d));
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(maze[i][j]!='X')
cacul(i,j);
}
}
while(true){
int t=sear();
if(t==-1) break;
sol(t);
ans++;
/*cout<<endl;
for(int i=0;i<n;i++){
cout<<maze[i]<<endl;
}*/
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(maze[i][j]!='X'&&maze[i][j]!='S')
cacul(i,j);
}
}
}
cout<<ans<<endl;
}
return 0;
}
sear()函数贪心选取影响最小的机枪点。
cacul()函数统计当前点影响的区域。
sol()函数放置机枪,然后把影响的区域置’S’,注意被影响的区域并不能置墙的值(‘X’)。