D-block tower--补题 dfs

题目的意思是:给一个n×m的矩阵,在每个矩形格子里建房子,要求可以尽量容纳多的人

            条件:蓝房子容纳100人,红房子容纳200人但是必须和蓝房子共用一条街道,平地可以建房子,有洞的地方不能建房子

                      输入 n,m (1 ≤ n, m ≤ 500)

          还有一个n×m的矩阵

          矩阵中#为洞,.为平地

        输出 

         k操作步骤数 0 ≤ k ≤ 106

         B x y (1 ≤ x ≤ n, 1 ≤ y ≤ m) — 建立蓝房子在(x, y)               

         R x y (1 ≤ x ≤ n, 1 ≤ y ≤ m) — 建立红房子在(x, y);                

         D x y (1 ≤ x ≤ n, 1 ≤ y ≤ m) —破坏房子(x, y).

解题的思路:理解题意,竟然要人数多,那肯定是红房子越多越好,但蓝房子肯定不为零。仔细一想,如果在一个         没有被分割的矩阵里,建到最后人数最多时,一定只有一个蓝房子,其它的都是红房子。刚开始的时         候我想用分情况来建房子,但是发现,情况考虑总是不周,总是会有很多蓝房子被孤立,而不是一         个。正在走迷宫,那样很容易孤立蓝房子,所以应该要倒着走。

        1,矩阵分为几个小矩阵(被#隔离开的),只要解决小矩阵里只有一个蓝房子,在循环到其它矩阵         2,把所有的'.'都建成蓝房子,然后再用dfs逐个找蓝房子它周围的相邻没被访问过的蓝房子,将其变成,并递归到相邻蓝房子的蓝房子                                                     3,然后倒叙把变成红房子的坐标输出(这个可以用栈,只会c语言,写栈太麻烦)

代码:

#include <stdio.h>
#include <stdlib.h>
char a[505][505];
struct stack
{
    int x;
    int y;
    int bo;
};
struct stack record[1000000];//开了一个结构体,来存放操作步骤,0 ≤ k ≤ 106
int count1=0,count2=0,count=0,n,m;//蓝房子操作,红房子和拆房子操作,红房子+蓝房子操作计数器
int dx[4]= {0,1,0,-1},dy[4]= {1,0,-1,0};//方向,找相邻蓝房子
int dfs(int x1,int y1)
{
    int i;
    for(i=0; i<4; i++)
    {
        int xx,yy;
        xx=x1+dx[i];
        yy=y1+dy[i];
        if(xx>=0&&xx<n&&yy>=0&&yy<m&&a[xx][yy]=='.')
        {
            record[count].x=xx;
            record[count].y=yy;
            record[count].bo=0;
            count++;
            count1++;
            record[count].x=xx;
            record[count].y=yy;
            record[count].bo=1;
            count2++;
            count++;
            a[xx][yy]='#';//蓝房子变红房子
            dfs(xx,yy);
        }
    }
    return 0;
}
int main()
{
    scanf("%d %d",&n,&m);
    int i,j;
    for(i=0; i<n; i++)
    {
        scanf("%s",a[i]);
    }
    for(i=0; i<n; i++)//大矩阵分成小矩阵
    {
        for(j=0; j<m; j++)
        {
            if(a[i][j]=='.')//进入一个小矩阵dfs小矩阵,第一个蓝房子不变红房子
            {
                a[i][j]='#';
                record[count].x=i;
                record[count].y=j;
                record[count].bo=0;
                count++;
                count1++;
                dfs(i,j);
            }
        }
    }
    int k=0;
    k=count1+count2*2;
    printf("%d\n",k);
    for(i=0; i<count; i++)
    {
        if(record[i].bo==0)
        {
            printf("B %d %d\n",record[i].x+1,record[i].y+1);
        }
    }
    for(i=count-1; i>=0; i--)//红房子步骤倒着输出,就可以保证最后一个红房子又蓝房子共用一条街道
    {
        if(record[i].bo==1)
        {
            printf("D %d %d\n",record[i].x+1,record[i].y+1);
            printf("R %d %d\n",record[i].x+1,record[i].y+1);
        }
    }
    return 0;

}

 

总结:1,逆向思维  2,刚学习算法,对dfs和bfs不熟悉,有种畏惧心理

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值