利用回溯法,具体代码如下:
#include<stdio.h>
#include<iostream>
using namespace std;
#define MAX 4 //n的最大值为4
void search(int m,int n,int &maxcount,int Res[],int Data[][MAX]); //回溯法求解
int CanPlace(int m,int n,int Res[],int Data[][MAX]); //判断在m位置处能不能放摄像头
void CheckResult(int n,int &maxcount,int Res[]); //更新结果
int main()
{
int i = 0,j = 0,n = 0; //矩形方格行列数
int maxcount = 0; //保存最终结果
int Data[MAX][MAX]; //存储区域信息,0代表空格,1代表墙
int Res[MAX*MAX] = {0}; //存储放摄像头位置
char c;
while(cin>>n) //文档尾结束
{
fflush(stdin);
maxcount = 0;
for(i = 0; i < n; i++) //读取数据
{
for(j = 0; j < n; j++)
{
cin>>c;
if(c == 'X' || c == 'x') //墙
{
Data[i][j] = 1;
}
else if(c == '.') //空格
{
Data[i][j] = 0;
}
else //其余情况
{
Data[i][j] = 0;
}
}
fflush(stdin);
}
search(0,n,maxcount,Res,Data);
cout<<maxcount<<endl; //输出结果
}
}
void search(int m,int n,int &maxcount,int Res[],int Data[][MAX]) //回溯法求解
{
if(m == n*n) //回溯结束条件
{
CheckResult(n,maxcount,Res);
return;
}
else //继续回溯
{
Res[m] = 0; //不放摄像头,递归搜索
search(m+1,n,maxcount,Res,Data);
if(CanPlace(m,n,Res,Data)) //放摄像头,递归搜索
{
Res[m] = 1;
search(m+1,n,maxcount,Res,Data);
}
}
}
int CanPlace(int m,int n,int Res[],int Data[][MAX]) //判断在m位置处能不能放摄像头
{
int i=0,j=0,row=0,col=0,flag1=0,flag2=0,flag=0;
row=m/n; //m处所对应的行
col=m%n; //m处所对应的列
i=row-1;
j=col-1;
if(Data[row][col]==1)return 0; //有墙不能放
while(i>=0)
{
if(Data[i][col]==1) //在这一列上有墙
{
flag1=1;
break;
}
if(Res[i*n+col]==1) //这一列已经放过摄像头
{
flag1=0;
break;
}
i--;
}
if(i<0)flag1=1;
while(j>=0)
{
if(Data[row][j]==1) //在这一行上有墙
{
flag2=1;
break;
}
if(Res[row*n+j]==1) //这一行已经放过摄像头
{
flag2=0;
break;
}
j--;
}
if(j<0)flag2=1;
flag=flag1*flag2; //两个条件同时为1,才可以放摄像头
return flag;
}
void CheckResult(int n,int &maxcount,int Res[]) //更新结果
{
int i=0,count=0;
for(i=0;i<n*n;i++)
{
count=count+Res[i]; //可放的摄像头数量
}
if(count>maxcount)maxcount=count; //更新最大值
}