SZUOJ-大作业

11 篇文章 0 订阅
7 篇文章 0 订阅


世界名画陈列馆由 mx n 个陈列室组成 为防止名画被盗,需要在陈列室中设置警卫机器人哨位 每个警卫机器人除了监视它所在的陈列室外,还可监视与它所在陈列室相邻的上、下、 左、右 4 个陈列室 设计一个算法,安排警卫机器人哨位,使得名画陈列馆中每一个陈列室都在警卫机器人 的监视之下,且所用的警卫机器人最少:

#include <iostream>
#include <string.h>
#include <cmath>
#include <windows.h>
#include <stdlib.h>
using namespace std;

int n,m,now;
bool map[25][25],ans[25][25];

inline bool covered(int x,int y)//判断棋子是否被填充或者已经越界 
{
    if (map[x][y]==true || (x-1>=1 && map[x-1][y]==true) || (x+1<=n && map[x+1][y]==true) || (y-1>=1 && map[x][y-1]==true) || (y+1<=m && map[x][y+1]==true))
        return(true);
    return(false);
}
//x,y为坐标,sum为放的格子总数,pre代表上一次放棋子的时候假设空白格子为(x,y),那么pre1==true的时候
//棋子中心放在了(x,y)上,pre2为true的时候放在了(x,y+1)上,pre3为true的时候放在了(x+1,y)上 
void find(int x,int y,int sum,bool pre1,bool pre2,bool pre3)
{
	//表示如果剩下的课放置的次数都填充了最大的5个还小于剩下的棋盘格子总数的时候,肯定不可以; 
    if (sum>now || (now-sum)*5<(n-x-1)*m) return;
    //已经到了最后一个格子 
    if (x==n && y==m)
    {
        if (covered(x,y)==false)
            sum++;
        //如果比上界要小,就保存结果并缩小上界 
		if (now-sum>=0)
		{
			for (int i=1;i<=n;i++)
				for (int j=1;j<=m;j++)
					ans[i][j]=map[i][j];
			if (covered(x,y)==false) ans[x][y]=true;
			now=sum-1;
		}
        return;
    }
    //如果要换行或者已经被填充为黑色的时候 
    if (y>m || covered(x,y)==true)
    {
    	//换行的时候把pre都置位f,不换行就保存pre继续dfs; 
        if (y+1<=m) find(x,y+1,sum,pre1,pre2,pre3);
        else find(x+1,1,sum,false,false,false);
        return;
    }
    //三个预判格子都为白色 
	if (y+1<=m && x+1<=n && covered(x+1,y)==false && covered(x,y+1)==false)
	{
		//棋子中心放在(x,y) 
		if (pre1==false)
		{
			map[x][y]=true;
			find(x,y+1,sum+1,true,false,false);
			map[x][y]=false;
		}
		if (sum>now || (now-sum)*5<(n-x-1)*m) return;
		//棋子中心放在(x+1,y) 
		if (pre2==false)
		{
			map[x+1][y]=true;
			find(x,y+1,sum+1,false,true,false);
			map[x+1][y]=false;
		}
		if (sum>now || (now-sum)*5<(n-x-1)*m) return;
		//棋子中心放在(x,y+1) 
		if (pre3==false)
		{
			map[x][y+1]=true;
			find(x,y+1,sum+1,false,false,true);
			map[x][y+1]=false;
		}
	}
	//(x,y+1)为黑的时候要中心放在(x+1,y)为最优的 
	else if (y+1<=m && x+1<=n && covered(x+1,y)==false && covered(x,y+1)==true)
	{
		map[x+1][y]=true;
		find(x,y+1,sum+1,false,true,false);
		map[x+1][y]=false;
	}
	//(x+1,y)为黑的时候要中心放在(x,y+1)为最优的  
	else if (y+1<=m && x+1<=n && covered(x+1,y)==true && covered(x,y+1)==false)
	{
		map[x][y+1]=true;
		find(x,y+1,sum+1,false,false,true);
		map[x][y+1]=false;
	} 
	//特判(n,m-1) 
	else if (y+1<=m && x+1>n)
	{
		map[x][y+1]=true;
		find(x,y+1,sum+1,true,true,false);
		map[x][y+1]=false;
	}
	//特判(n-1,m) 
	else if (y+1>m)
	{
		map[x+1][y]=true;
		find(x,y+1,sum+1,false,false,false);
		map[x+1][y]=false;
	}
}

void display()//画出棋盘 
{
	int i,j,k;
    cout<<"┏";
    for (i=1;i<m;i++) cout<<"━┯";
    cout<<"━┓"<<endl;
    for (i=0;i<n;i++)
    {
        if (i)
        {
            cout<<"┠";
            for( k=1;k<m;k++) cout<<"─┼";
            cout<<"─┨"<<endl;
        }
        cout<<"┃";
        for(j=0;j<m;j++)
        {
            if(j) cout<<"│";
            if(ans[i+1][j+1]) cout<<"●";
            else cout<<"  ";
        }
        cout<<"┃"<<endl;
    }
    cout<<"┗";
    for(i=1;i<m;i++)
        cout<<"━┷";
    cout<<"━┛"<<endl;
}

int main()
{
    cin>>n>>m;
    int s=GetTickCount();
    now=ceil((n*m)/3.0);
    find(1,1,0,false,false,false);
    now++;
    cout<<now<<endl;
	display();
	int e=GetTickCount();
	cout<<(e-s)/1000.0<<endl;//计时 
    return(0);
}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值