浙江大学ZOJ 1002题 详解

欢迎来看一个小新手的博客


  • 前几天第一次代表内蒙古大学参加了在上海大学举办的ec-final 被狠虐了一顿之后发现了自己不足,和真正的一流大学相比天差地别,于是回来打算尽自己努力练一下自己的算法,起码要每天最少刷一道题吧毕竟已经大二,希望尽力向深黑幻想那样的队伍靠齐吧(虽然真的差的太多了)。于是选择了浙江大学的OJ作为平台,怎么说呢,加油吧。

    话不多说,在自己英语水平极其有限的情况下强行翻译了1002这道题,题目的大概意思是说先要输入一个int类型的数代表了地图的大小(长等于宽),
    然后输入一个地图,类似于

    .X..
    ….
    XX..
    ….

    这样的地图,现在你要在地图里面放置炮楼,.的地方都代表是空地,X的地方都代表是墙,炮楼会向炮楼的一横排和一竖排发射炮弹,但是墙会将炮弹阻拦下来(也就是炮弹不会打到墙的另外一面),为了防止炮楼互相攻击,问你这一整个地图里面能放置最多多少个炮楼。(有点类似于变种八皇后吧)。我能想到的也就是暴力一点的解法深度优先搜索。然后就是上代码;

#include<iostream>
using namespace std;
int n;
char map[100][100];

int max_num=0;//用来记录每一回查找到的最大值
int max_sum = 0;//用来比较每次查找的最大值的其中的最大值
int sum=0;//用来记录当前查找到的已经放置的炮楼的数量
int flag=0;//当作标记,用来判断当前这个点有没有放置炮楼
//递归函数
int blockhouse ()
{
    //遍历的地图查找能放置炮楼的点
    for(int x=0;x<n;x++)
    {
        for(int y=0;y<n;y++)
        {
            max_num=0;
            flag=0;//标记初始化
            if(map[x][y]=='.')
            {
                //如果当前点能够放置炮楼
                sum++;
                flag=1;
                char map_copy[100][100];//记录没放炮楼前的地图
                for(int i=0;i<n;i++)
                {
                    for(int j=0;j<n;j++)
                    {
                        map_copy[i][j]=map[i][j];
                    }
                }
                //放置炮楼,并且将炮楼四个方向的空地全都打上标记,表示这些点不能够放置炮楼
                //左面
                map[x][y]='1';
                for(int i=y-1;i>=0;i--)
                {
                    if(map[x][i]=='X')
                    {
                        break;
                    }
                    map[x][i]='1';
                }

                //判断右面
                for(int i=y+1;i<n;i++)
                {
                    if(map[x][i]=='X')
                    {
                        break;
                    }
                    map[x][i]='1';

                }
                //判断上面
                for(int i=x-1;i>=0;i--)
                {
                    if(map[i][y]=='X')
                    {
                        break;
                    }
                    map[i][y]='1';
                }
                //判断下面
                for(int i=x+1;i<n;i++)
                {
                    if(map[i][y]=='X')
                    {
                        break;
                    }
                    map[i][y]='1';
                }
                //基于现在的情况继续查找下一个能够放置炮楼的分支
                sum = blockhouse()-1;
                //将整个地图复原至上层分支,方便此层分支的另外一种情况分析
                for(int i=0;i<n;i++)
                {
                    for(int j=0;j<n;j++)
                    {
                        map[i][j]=map_copy[i][j];
                    }
                }



            }
            //sum 与flag进行复原至上层分支的情况
            if(flag==1)
            {
                    sum--;
                    flag=0;
            }
            //最大数量判断
            if(max_sum<max_num)
            {
                    max_sum = max_num;

                    max_num=0;
            }
            //递归出口,即为查遍整个地图,分支退出前检查最大值问题
            if(x==n-1&&y==n-1)
            {
                if(sum>max_num)
                {
                    max_num = sum;
                    //cout<<max_num<<endl;
                }
                return sum;
            }

        }
    }


}
int main()
{
    while(cin>>n)
    {
        if(n==0)
        {
            break;
        }

        for(int i=0;i<n;i++)    
        {
            for(int j=0;j<n;j++)
            {
                cin>>map[i][j];
            }
        }
        blockhouse();
        cout<<max_sum<<endl;
        max_sum=0;
        max_num=0;
    }

虽然代码写的比较烂,但是整体思路大概就是这个样子。

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值