usaco The Castle

本文探讨了如何通过二维矩阵表示的房间信息,优化房间布局,计算最大房间大小及合并后的房间信息,包括面积、位置及操作策略。

 题目给了一个二维矩阵,矩阵的每个数字代表一个单位的面积,每个数字转换为二进制,这个四位二进制数的每一位,分别代表了自己的东南西北是否有墙。

题目求房间的数目,最大的自然房间的大小,拆掉某一堵墙之后的可能会造成某两个自然房间合并,求合成最大房间的面积,以及拆除的抢的坐标,以及位置

做法是,对单位面积进行染色,可以相互联通的区域就是一个房间。

再设一个数组Size表示染色为i的房间的大小,

然后枚举拆掉每堵墙之后的情况,合成的房间的大小就是自己和自己相邻的单位面积所代表的房间大小(Size中的值)相加

/*
ID: modengd1
PROG: castle
LANG: C++
*/
#include <iostream>
#include <stdio.h>
#include <memory.h>
using namespace std;
int input[52][52];
int color[52][52];
int Size[255];
int dx[4]={0,-1,0,1},dy[4]={-1,0,1,0};//此处根据题意给的从左往右每位代表的墙的情况设置,提高了代码重用率,但增加了编程复杂度
//染色,C为当前所染的颜色
int dfs(int x,int y,int C)
{
    int ret=1;
    color[x][y]=C;
    for(int i=0;i<4;i++)
    {
        if((input[x][y]&(1<<i))==0&&color[x+dx[i]][y+dy[i]]==0)
        {
            ret+=dfs(x+dx[i],y+dy[i],C);
        }
    }
    return ret;
}
/*A墙去掉之后,和B墙去掉之后,得到的结果作比较,如果A墙去掉之后更加符合题目要求的
房子最大,最靠西,最靠南,则返回true,否则返回false,   ch表示时E墙还是N墙,lar代表去掉这堵墙之后构造的房间的面积
*/
bool isAbigThanB(int i1,int j1,int ch1,int lar1,int i2,int j2,int ch2,int lar2)
{
    //大小不一样,直接根据大小决定是否替换
    if(lar1!=lar2)
        return lar1>lar2;
    //不再同一个垂直线上时,比较j
    if(j1!=j2)
        return j1<j2;
    //在同一个水平线上时,N比E所代表的更加靠西
    if(ch1!=ch2)
        return ch1>ch2;
    //程序执行到此说明,房间大小一样,且按照最靠西的标准无法确定,则选择最靠南的
    return i1>i2;
}
int main()
{
    freopen("castle.in","r",stdin);
    freopen("castle.out","w",stdout);
    int N,M,c;
    int rooms,lar,lar2,x,y;
    char ch;
    memset(color,0,sizeof(color));
    memset(Size,0,sizeof(Size));
    scanf("%d%d",&N,&M);
    for(int i=1;i<=M;i++)
    {
        for(int j=1;j<=N;j++)
        {
            scanf("%d",&input[i][j]);
        }
    }
    //lar表示最大的自然房间的大小
    c=1;lar=0;
    //染色
    for(int i=1;i<=M;i++)
    {
        for(int j=1;j<=N;j++)
        {
            if(color[i][j]==0)
            {
                Size[c]=dfs(i,j,c);
                lar=max(lar,Size[c]);
                c++;
            }
        }
    }
    rooms=c-1;
    lar2=0;
    //lar2表示最大的合成房间的大小
    //模拟去掉每堵墙
    for(int i=1;i<=M;i++)
    {
        for(int j=1;j<=N;j++)
        {
            //假设去掉自己的北面,也就是相邻的南面
            if(color[i][j]!=color[i-1][j])
            {
                int temp=Size[color[i][j]]+Size[color[i-1][j]];
                if(isAbigThanB(i,j,'N',temp,x,y,ch,lar2))
                {
                    x=i;y=j;
                    lar2=temp;
                    ch='N';
                }
            }
            //假设去掉自己的东面,也就是相邻的西部
            if(color[i][j]!=color[i][j+1])
            {
                int temp=Size[color[i][j]]+Size[color[i][j+1]];
                if(isAbigThanB(i,j,'E',temp,x,y,ch,lar2))
                {
                    x=i;y=j;lar2=temp;
                    ch='E';
                }
            }
        }
    }
    cout<<rooms<<endl;
    cout<<lar<<endl;
    cout<<lar2<<endl;
    cout<<x<<' '<<y<<' '<<ch<<endl;
    return 0;
}

  

转载于:https://www.cnblogs.com/modengdubai/p/4774708.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值