USACO Section2.1 The Castle 解题报告

    castle解题报告 —— icedream61 博客园(转载请注明出处)
------------------------------------------------------------------------------------------------------------------------------------------------
【题目】
  有N×M的矩阵,边框都是实际存在的“墙”。如下图:

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

  上图就是N=4,M=7的一种情况,#表示墙,|表示没有墙。
  没有墙的连通块,就被认为是一个房间。例如图中,(2,6)是一个面积为1的房间,(1,3)(1,4)(2,4)则是一个面积为3的房间。
  现在请你打破一面墙,从而连通两个房间得到一个更大的房间。请你求出破出房间面积最大的情况,并给出下列输出。(例如图中就是打破箭头所指的墙)
【输入格式】
  第一行两个数,M和N。
  下面N行,每行M个数,依次是每个点四周墙的情况,各由一个数代表。这个数由四个数中的几个相加而成:
    1: 左面有墙
    2: 上面有墙
    4: 右面有墙
    8: 下面有墙
  例如,11=8+2+1,表示此点除了右面,余下三面都有墙。
【输出格式】
  第一行给出初始房间数。(例如图中有5个连通块,即5个房间)
  第二行给出初始最大的房间。(图中便是(1,1)所在房间)
  第三行给出打破一面墙所得的房间面积最大值。
  第四行给出打破的是哪一面墙。(例如本题输出样例,便表示是(4,1)东面的墙)
  注意:描述墙的方式,是用墙左面或下面的点的左边,加上墙相对点的方向(‘N‘or‘E‘)。如果有多面墙可供打破,那么优先选择最左面的,再优先最下面的,再优先墙相对点的方向为‘N‘的。
【数据范围】
  1<=N,M<=50
【输入样例】
  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
【输出样例】
  5
  9
  16
  4 1 E
------------------------------------------------------------------------------------------------------------------------------------------------
【分析】
  裸FloodFill。
  好好画图,注意细节,需要存的大数组也就是每个点的信息和Fill出的每块的大小了。边是不能存的,计算一下会发现空间不够。
------------------------------------------------------------------------------------------------------------------------------------------------
【总结】
  题目开始难起来了,要开始分析时空复杂度了。不能无脑刷了!
  第一次,超空间了,没计算空间。
    Edge定义成了邻接矩阵,2500²=6,250,000≈6M,由于是int,故6×4=24M,显然超过了USACO十几M内存的限制。
  第二次,第七个点被卡主,原因是运行时间远超1s。
    为了调试方便,觉得应该不会超时,就没删屏幕输出。
  第三次,仍是第七个点,原因是运行时错误。
    这数据是极限数据,N=M=50,所有位置都有墙。显然,应该是程序没判断好边界情况。
    调试过程中,慢慢发现,问题出在超内存上!
    墙满的时候,邻接表还不如邻接矩阵呢。。我竟然忘了这个!既然邻接表可能被占满,那显然比邻接矩阵更占空间啊……
    仔细一想,我SB了……这题根本不用存边嘛……直接存点的信息就好了,一个裸的FloodFill愣是被我搞得如此复杂……
  经过几次提交和修改,第七次,AC。
  代码得改漂亮些……不能太难看了-.-

------------------------------------------------------------------------------------------------------------------------------------------------

【代码】

 1 /*
 2 ID: icedrea1
 3 PROB: castle
 4 LANG: C++
 5 */
 6
 7 #include <iostream>
 8 #include <fstream>
 9 using namespace std;
10
11 int N,M,num[1+50*50];
12 struct MapNode
13 {
14     int mark;
15     int wall;
16 }Node[1+50][1+50]; // Node[i][j]: i行j列的点
17
18 void Fill(int x,int y,int mark)
19 {
20     int wall=Node[x][y].wall;
21     Node[x][y].mark=mark; ++num[mark];
22     if(y>1 && (wall&1)==0 && Node[x][y-1].mark==0) Fill(x,y-1,mark); // 1 west (x,y-1)
23     if(x>1 && (wall&2)==0 && Node[x-1][y].mark==0) Fill(x-1,y,mark); // 2 north (x-1,y)
24     if(y<M && (wall&4)==0 && Node[x][y+1].mark==0) Fill(x,y+1,mark); // 4 east (x,y+1)
25     if(x<N && (wall&8)==0 && Node[x+1][y].mark==0) Fill(x+1,y,mark); // 8 south (x+1,y)
26 }
27 int FloodFill()
28 {
29     int mark,sum;
30     for(mark=1,sum=0;sum<N*M;++mark) // sum==N×M说明填满了,FlookFill结束
31     {
32         // 本次FlookFill的编号为mark
33         int x,y;
34         bool p=true;
35         for(int i=1;i<=N&&p;++i)
36             for(int j=1;j<=M&&p;++j)
37                 if(Node[i][j].mark==0) { x=i; y=j; p=false; }
38         // 从(x,y)开始本次FloodFill
39         Fill(x,y,mark); sum+=num[mark];
40     }
41     return mark-1;
42 }
43
44 int main()
45 {
46     ifstream in("castle.in");
47     ofstream out("castle.out");
48
49     in>>M>>N;
50     for(int i=1;i<=N;++i)
51         for(int j=1;j<=M;++j) in>>Node[i][j].wall;
52
53     int cnt=FloodFill(),room=0;
54     for(int i=1;i<=cnt;++i)
55         if(num[i]>room) room=num[i];
56
57     int x,y,area=0; char wall;
58     for(int j=1,t;j<=M;++j)
59         for(int i=N;i>=1;--i)
60         {
61             t=num[Node[i][j].mark]+num[Node[i-1][j].mark];
62             if(i>1 && Node[i][j].mark!=Node[i-1][j].mark && t>area) { area=t; x=i; y=j; wall=‘N‘; }
63             t=num[Node[i][j].mark]+num[Node[i][j+1].mark];
64             if(j<M && Node[i][j].mark!=Node[i][j+1].mark && t>area) { area=t; x=i; y=j; wall=‘E‘; }
65         }
66
67     out<<cnt<<endl;
68     out<<room<<endl;
69     out<<area<<endl;
70     out<<x<<" "<<y<<" "<<wall<<endl;
71
72     in.close();
73     out.close();
74     return 0;
75 }
时间: 2024-12-17 09:36:31

USACO Section2.1 The Castle 解题报告的相关文章

USACO Section2.1 Healthy Holsteins 解题报告 【icedream61】

holstein解题报告 ------------------------------------------------------------------------------------------------------------------------------------------------[题目] 你需要给一头奶牛制定最优的喂养计划. 有V种维他命,每天对于每种维他命,牛都有需要达到的指标: 同时你有G种饲料,编号依次为1到G,每种维他命在每种饲料中所蕴含的量都会给你.

USACO Section2.1 Hamming Codes 解题报告 【icedream61】

hamming解题报告------------------------------------------------------------------------------------------------------------------------------------------------[题目] 找出N个二进制数,每个数有B位,使得各数两两之间“海明距离”至少为D.(若有多组解,输出字典序最小的.) 海明距离是指:两个二进制数不同二进制位的个数.[数据范围] 1<=N<=

USACO Section2.3 Controlling Companies 解题报告 【icedream61】

concom解题报告------------------------------------------------------------------------------------------------------------------------------------------------[题目] 有至多100个公司,每个公司可能会有很多子公司,请你输出每个公司有哪些子公司. B是A的子公司,有以下两种情况: 1. A拥有B超过50%的股份 2. A某些子公司(包括A自己)各拥

USACO Section2.2 Runaround Numbers 解题报告 【icedream61】

runround解题报告------------------------------------------------------------------------------------------------------------------------------------------------[题目] 给你一个数M,找出第一个比它大的循环数. 循环数:不包括0.没有重复数字,并且有循环性质的正整数. 循环性质:以81362为例 1.找到最高位,是8,那么往下数8位,依次是1,3

USACO Section2.3 Zero Sum 解题报告 【icedream61】

zerosum解题报告------------------------------------------------------------------------------------------------------------------------------------------------[题目] 给你N. 把1到N依次写出,每相邻两个数字中间加上一个字符,三选一:'+','-',' '. 如此,便可形成很多表达式,把其中计算结果为0的按字典序输出.[数据范围] 3<=N<

USACO Section2.3 Money Systems 解题报告 【icedream61】

money解题报告------------------------------------------------------------------------------------------------------------------------------------------------[题目] 你有V种硬币,每种硬币面值都告诉你. 请问,用它们凑出面值N,总共有多少种情况?[数据范围] 1<=V<=25 1<=N<=10000 数据保证,总情况数不超过long

USACO Section2.2 Party Lamps 解题报告 【icedream61】

lamps解题报告------------------------------------------------------------------------------------------------------------------------------------------------[题目] N个灯,编号1~N.有4个开关,和C次改变某个开关状态的机会,试问最终所有灯的亮灭情况可能有哪些? 一号开关:改变所有灯的状态. 二号开关:改变所有奇数号灯的状态. 三号开关:改变所有

USACO Section2.1 Ordered Fractions 解题报告

frac1解题报告 —— icedream61 博客园(转载请注明出处)------------------------------------------------------------------------------------------------------------------------------------------------[题目] 给你N,对于所有的既约分数i/j(1<=j<=N,0<=i<=j),升序排列输出(重复则只留j最小的).[数据范围]

USACO Section2.3 Longest Prefix 解题报告 【icedream61】

prefix解题报告------------------------------------------------------------------------------------------------------------------------------------------------[题目] 给你许多子串P和一个长字符串S,请问S的前缀中能用这些子串(可以重复使用子串)组合的最长的一个长度是多少?[数据范围] P的长度在1-10之内,子串个数在1-200之内 S的长度在1