USACO The Castle

傻卵DFS吧,然而WA了两发我也是醉。English渣到爆, farthest to the west是最西面而不是离西面最远,嗯。

题意,给一个n*m的地图,把数字写成2进制,共4位,每一位代表一个方向是否有墙。问房间数,最大房间的size,去掉一面墙后合并的两个房间的最大size,要求去掉的墙最西最南,方向先N后E。

做法:dfs一遍,给每个房间编号,记录每个房间的size,得出房间数和最大size。按照优先级跑一遍,每次判断位置上是否有墙,墙两边是否房间不同,两房间之和是否大于当前最大值,均正确后更新。

代码:

/*
ID: jlw44671
PROG: castle
LANG: C++
*/
#include <cstdio>
#include <iostream>
#include <cstring>
#include <queue>
#include <algorithm>
#include <cmath>
using namespace std;

int pic[55][55];
bool vis[55][55];
int m,n;
int tag[55][55];
int size[55*55];
int M,M2,tagpos;
bool flag;
int recx,recy;

void dfs(int x,int y)
{
    vis[x][y]=true;
    tag[x][y]=tagpos;
    size[tagpos]++;
    if(!(pic[x][y]&1)&&!vis[x][y-1])dfs(x,y-1);
    if(!(pic[x][y]&2)&&!vis[x-1][y])dfs(x-1,y);
    if(!(pic[x][y]&4)&&!vis[x][y+1])dfs(x,y+1);
    if(!(pic[x][y]&8)&&!vis[x+1][y])dfs(x+1,y);
    return;
}

int main()
{
    freopen("castle.in","r",stdin);
    freopen("castle.out","w",stdout);
    memset(vis,false,sizeof(vis));
    scanf("%d %d",&m,&n);
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
            scanf("%d",&pic[i][j]);
    }
    M=0;
    tagpos=0;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            if(!vis[i][j]){tagpos++;dfs(i,j);}
        }
    }
    for(int i=1;i<=tagpos;i++)
        M=max(M,size[i]);
    M2=0;
    printf("%d\n%d\n",tagpos,M);
    for(int j=1;j<=m;j++)
        for(int i=n;i>=1;i--)
        {
            if(i!=1&&(pic[i][j]&2)&&(tag[i][j]!=tag[i-1][j])&&(M2<size[tag[i][j]]+size[tag[i-1][j]]))
            {
                flag=true;
                recx=i;
                recy=j;
                M2=size[tag[i][j]]+size[tag[i-1][j]];
            }
            if(j!=m&&(pic[i][j]&4)&&(tag[i][j]!=tag[i][j+1])&&(M2<size[tag[i][j]]+size[tag[i][j+1]]))
            {
                flag=false;
                recx=i;
                recy=j;
                M2=size[tag[i][j]]+size[tag[i][j+1]];
            }
        }
    printf("%d\n%d %d %c\n",M2,recx,recy,flag==true?'N':'E');
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值