题目的意思是:给一个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不熟悉,有种畏惧心理