USACO 2.1.1The Castle

The Castle
IOI'94 - Day 1

In a stroke of luck almost beyond imagination, Farmer John wassent a ticket to the Irish Sweepstakes (really a lottery) for hisbirthday. This ticket turned out to have only the winning numberfor the lottery! Farmer John won a fabulous castle in the Irishcountryside.

Bragging rights being what they are in Wisconsin, Farmer Johnwished to tell his cows all about the castle. He wanted to knowhow many rooms it has and how big the largest room was. In fact,he wants to take out a single wall to make an even bigger room.

Your task is to help Farmer John know the exact room count andsizes.

The castle floorplan is divided into M (wide) by N (1 <=M,N<=50)square modules. Each such module can have between zero and fourwalls. Castles always have walls on their "outer edges" to keepout the wind and rain.

Consider this annotated floorplan of a castle:

     1   2   3   4   5   6   7
   #############################
 1 #   |   #   |   #   |   |   #
   #####---#####---#---#####---#   
 2 #   #   |   #   #   #   #   #
   #---#####---#####---#####---#
 3 #   |   |   #   #   #   #   #   
   #---#########---#####---#---#
 4 # ->#   |   |   |   |   #   #   
   ############################# 

#  = Wall     -,|  = No wall
-> = Points to the wall to remove to
     make the largest possible new room

By way of example, this castle sits on a 7 x 4 base. A "room" includesany set of connected "squares" in the floor plan. This floorplan containsfive rooms (whose sizes are 9, 7, 3, 1, and 8 in no particular order).

Removing the wall marked by the arrow merges a pair of rooms tomake the largest possible room that can be made by removing a singlewall.

The castle always has at least two rooms and always has a wallthat can be removed.

PROGRAM NAME: castle

INPUT FORMAT

The map is stored in the form of numbers, one number for each module,M numbers on each of N lines to describe the floorplan. The inputorder corresponds to the numbering in the example diagram above.

Each module number tells how many of the four walls exist andis the sum of up to four integers:

  • 1: wall to the west
  • 2: wall to the north
  • 4: wall to the east
  • 8: wall to the south

Inner walls are defined twice; a wall to the south in module 1,1is also indicated as a wall to the north in module 2,1.

Line 1:Two space-separated integers: M and N
Line 2..:M x N integers, several per line.

SAMPLE INPUT (file castle.in)

7 4
11 6 11 6 3 10 6
7 9 6 13 5 15 5
1 10 12 7 13 7 5
13 11 10 8 10 12 13

OUTPUT FORMAT

The output contains several lines:

Line 1:The number of rooms the castle has.
Line 2:The size of the largest room
Line 3:The size of the largest room creatable by removing one wall
Line 4:The single wall to remove to make thelargest room possible

Choose the optimal wall to remove from the set of optimal wallsby choosing the module farthest to the west (and then, if stilltied, farthest to the south). If still tied, choose 'N' before 'E'.Name that wall by naming the module that borders it on either thewest or south, along with a direction of N or E giving the locationof the wall with respect to the module.

SAMPLE OUTPUT (file castle.out)

5
9
16
4 1 E
 

题意:先来解释一下数据。第一行输入矩阵的列和行,接下来的数据描述了每个方间周围的墙有哪些。比如11说明方间的北边,南边,西边有墙。所以给出矩阵相当于给了地图。题目要求找出最大的房间的面积,并确定共有几间房,可以通过推到哪面墙来扩大房间面积,使之最大(注意,有多面墙可选时,要选择最西边的,若还有多个选择,要选择最南面的墙)。

思路:首先,求几个房间和最大房间的面积,可以用DFS求连通分量的个数,得先把数字转化为01地图,在进行搜索。注意在计算面积时,只有是房间才可以累加,房间周围的没墙的地方不能算入。同时,在遍历时,不同的房间可以用编号记录一下,不同的面积也要记录一下。可在下一步时使用。其次,是枚举每一面墙,只要它的两边不是同一个房间就可以推倒,然后找推倒墙后面积最大的。

源代码:

/*
ID: supersnow0622
PROG: castle
LANG: C++
*/
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int arr[200][200];
int dir[4][2]={{-1,0},{0,-1},{0,1},{1,0}};
int M,N,m,n,in,countArea=0,countNum=2;
int record[3000];
void dfs(int i,int j)
{
  int newr,newc;
    arr[i][j]=countNum;
  if(i%2!=0&&j%2!=0)
    countArea++;
  for(int k=0;k<4;k++)
  {
      newr=i+dir[k][0];
      newc=j+dir[k][1];
      if(newr>=0&&newr<n&&newc>=0&&newc<m&&arr[newr][newc]==0)
        dfs(newr,newc);
  }
}
int main() {
    ofstream fout ("castle.out");
    ifstream fin ("castle.in");
    fin>>M>>N;
    m=2*M;n=2*N;
    int max=0,temp,row,col;
    for(int i=0;i<=n;i++)
      for(int j=0;j<=m;j++)
      {
       if((i%2==0||j%2==0)&&i!=0&&j!=0&&i!=n&&j!=m)arr[i][j]=0;
       if(i%2!=0&&j%2!=0)
       {
           arr[i][j]=0;
        fin>>in;
        if(in==1)
          arr[i-1][j-1]=arr[i][j-1]=arr[i+1][j-1]=1;
        else if(in==2)
          arr[i-1][j-1]=arr[i-1][j]=arr[i-1][j+1]=1;
        else if(in==3)
          arr[i-1][j-1]=arr[i][j-1]=arr[i+1][j-1]=arr[i-1][j]=arr[i-1][j+1]=1;
        else if(in==4)
          arr[i-1][j+1]=arr[i][j+1]=arr[i+1][j+1]=1;
        else if(in==5)
          arr[i-1][j-1]=arr[i][j-1]=arr[i+1][j-1]=arr[i-1][j+1]=arr[i][j+1]=arr[i+1][j+1]=1;
        else if(in==6)
          arr[i-1][j-1]=arr[i-1][j]=arr[i-1][j+1]=arr[i][j+1]=arr[i+1][j+1]=1;
        else if(in==7)
          arr[i-1][j-1]=arr[i][j-1]=arr[i+1][j-1]=arr[i-1][j+1]=arr[i][j+1]=arr[i+1][j+1]=arr[i-1][j]=1;
        else if(in==8)
          arr[i+1][j-1]=arr[i+1][j]=arr[i+1][j+1]=1;
        else if(in==9)
          arr[i-1][j-1]=arr[i][j-1]=arr[i+1][j-1]=arr[i+1][j]=arr[i+1][j+1]=1;
        else if(in==10)
          arr[i-1][j-1]=arr[i-1][j]=arr[i-1][j+1]=arr[i+1][j-1]=arr[i+1][j]=arr[i+1][j+1]=1;
        else if(in==11)
          arr[i-1][j-1]=arr[i-1][j]=arr[i-1][j+1]=arr[i+1][j-1]=arr[i+1][j]=arr[i+1][j+1]=arr[i][j-1]=1;
        else if(in==12)
          arr[i-1][j+1]=arr[i][j+1]=arr[i+1][j+1]=arr[i+1][j-1]=arr[i+1][j]=1;
        else if(in==13)
          arr[i-1][j-1]=arr[i][j-1]=arr[i+1][j-1]=arr[i-1][j+1]=arr[i][j+1]=arr[i+1][j+1]=arr[i+1][j]=1;
        else if(in==14)
          arr[i-1][j-1]=arr[i-1][j]=arr[i-1][j+1]=arr[i+1][j-1]=arr[i+1][j]=arr[i+1][j+1]=arr[i][j+1]=1;
        else if(in==15)
          arr[i][j-1]=arr[i-1][j-1]=arr[i-1][j]=arr[i-1][j+1]=arr[i+1][j-1]=arr[i+1][j]=arr[i+1][j+1]=arr[i][j+1]=1;
       }
      }
      for(int i=0;i<n;i++)
        for(int j=0;j<m;j++)
      {
          if(arr[i][j]==0)
          {
              dfs(i,j);
              if(countArea>max)
                   max=countArea;
               record[countNum]=countArea;
               countNum++;
              countArea=0;
          }
      }
   fout<<countNum-2<<endl;
      fout<<max<<endl;
      max=0;
      for(int i=n-1;i>=1;i--)
        for(int j=1;j<m;j++)
      {
          if(arr[i][j]==1)
           {
               if(arr[i][j-1]!=arr[i][j+1])
               {
                 temp=record[arr[i][j-1]]+record[arr[i][j+1]];
                 if(max<temp)
                 {
                     max=temp;row=i;col=j;
                 }
                  else if(max==temp)
                 {
                     if(j<col){row=i;col=j;}
                     if(j==col&&i>row){row=i;col=j;}
                 }
               }

               if(arr[i-1][j]!=arr[i+1][j])
               {
                 temp=record[arr[i-1][j]]+record[arr[i+1][j]];
                 if(max<temp)
                    {
                     max=temp;row=i;col=j;
                    }
                  else if(max==temp)
                 {
                     if(j<col){row=i;col=j;}
                     if(j==col&&i>row){row=i;col=j;}
                 }

               }
           }
      }
      fout<<max<<endl;
      if(row%2==0)
       fout<<row/2+1<<" ";
       else fout<<(row-1)/2+1<<" ";
      if(col%2!=0)
       fout<<col/2+1<<" ";
       else fout<<col/2<<" ";
     if(row%2!=0&&col%2==0)
      fout<<"E";
     else if(row%2==0&&col%2!=0)
      fout<<"N";
    return 0;
}





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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值