经典回溯-安装摄像头

数组ans用于记录已安装摄像头的点

 

#include <iostream>
#include <string.h>
#include <string>
#include <stdio.h>
using namespace std;
int  ma[20],ans[20],maxn;
int n;
//函数声明
bool is_catch(int x,int y);
void read();
void dp(int cou);
//函数定义
void read()
{
    while(cin>>n)
    {
        memset(ans,0,sizeof(ans));
        memset(ma,0,sizeof(ma));
        for(int i=0;i<20;i++)
        {
          ma[i]=0;
          ans[i]=0;
        }
        maxn=0;
        char cc;
        for(int i=1;i<=n*n;i++)
            {
                cin>>cc;
                if(cc=='X')
                    ma[i]=2;//2代表障碍物
            }
        dp(0);
        cout<<maxn<<endl;
    }
    return;
}
void dp(int cou)
{
    int i,j;
    for(i=1;i<=n*n;i++)//检查每个点是否能被摄像头抓取到
    {
        if(ma[i]==2)
            continue;
        for(j=0;j<cou;j++)
            if(is_catch(ans[j],i)) break;
        if(j==cou)//此点未被摄像头抓取到
            break;
    }
    if(i==(n*n+1))//所有点都被抓取到,则为一组解
    {
        if(maxn<cou)
            maxn=cou;
        return;
    }
    for(i=1;i<=n*n;i++)
    {
        if(ma[i]==2)
            continue;
         for(j=0;j<cou;j++)
        {
            if(is_catch(ans[j],i))
            break;
        }
        if(j==cou)//该位置可以放置摄像头
        {
            ans[cou]=i;
            dp(cou+1);
        }
    }
}
//判断当前摄像头是否可拍摄到此点
bool is_catch(int x,int y)//x为摄像头,y为需要判断的点
{
    if(x==y)
        return true;
    bool flag=false;
    int hang=(x-1)/n+1;
    for(int i=x-1;i>0;i--)//同行左面
    {
        if((i-1)/n+1 != hang || ma[i]==2)
            break;
        if(i==y)
        {
            flag=true;
            break;
        }
    }
    if(flag)
        return true;
    for(int i=x+1;i<=17;i++)//同行右面
    {
        if((i-1)/n+1 != hang || ma[i]==2)
            break;
        if(i==y)
        {
            flag=true;
            break;
        }
    }
    if(flag)
        return true;
    for(int i=x-n;i>0;i=i-n)//同列上面
    {
        if(ma[i]==2)
            break;
        if(i==y)
        {
            flag=true;
            break;
        }
    }
    if(flag)
        return true;
    for(int i=x+n;i<=n*n;i=i+n)//同列下面
    {
        if(ma[i]==2)
            break;
        if(i==y)
        {
            flag=true;
            break;
        }
    }
    return flag;

}

int main()
{
    read();
    return 0;
}


http://icpc.njust.edu.cn/Problem/Local/1014/

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值