usaco6.1.2 A Rectangular Barn

这篇博客讲述了农场主约翰计划扩大奶牛业务,需要购买更多奶牛并建造新牛棚。他买下了一块矩形土地,但由于部分区域损坏无法使用。约翰需要找出能建造的最大矩形牛棚面积,即不包括损坏区域的最大矩形区域。博客包括问题描述、输入输出格式、样例及代码分析。
部署运行你感兴趣的模型镜像

一 原题

A Rectangular Barn

Mircea Pasoi -- 2003

Ever the capitalist, Farmer John wants to extend his milking business by purchasing more cows. He needs space to build a new barn for the cows.

FJ purchased a rectangular field with R (1 ≤ R ≤ 3,000) rows numbered 1..R and C (1 ≤ C ≤ 3,000) columns numbered 1..C. Unfortunately, he realized too late that some 1x1 areas in the field are damaged, so he cannot build the barn on the entire RxC field.

FJ has counted P (0 ≤ P ≤ 30,000) damaged 1x1 pieces and has asked for your help to find the biggest rectangular barn (i.e., the largest area) that he can build on his land without building on the damaged pieces.

PROGRAM NAME: rectbarn

INPUT FORMAT

  • Line 1: Three space-separated integers: R, C, and P.
  • Lines 2..P+1: Each line contains two space-separated integers, r and c, that give the row and column numbers of a damaged area of the field

SAMPLE INPUT (file rectbarn.in)

3 4 2
1 3
2 1

OUTPUT FORMAT

  • Line 1: The largest possible area of the new barn

SAMPLE OUTPUT (file rectbarn.out)

6

OUTPUT DETAILS

  1 2 3 4
 +-+-+-+-+
1| | |X| |
 +-+-+-+-+
2|X|#|#|#|
 +-+-+-+-+
3| |#|#|#|
 +-+-+-+-+
Pieces marked with 'X' are damaged and pieces marked with '#' are part of the new barn. 


二 分析

和5.3.4 Big Barn非常类似。只不过5.3.4要求找出所有无障碍的正方形,现在条件放松了,找出所有无障碍的长方形。
初始的想法还是动规求出以点(i,j)为右下角的面积最大的长方形,但这样的状态表示并不满足最优子结构。
正确思路是:答案里面积最大的长方形一定是无法再向上、左、右扩张的。我们可以定义Up[i][j]表示点(i,j)最多能向上延伸多少格,用Left[i][j]和Right[i][j]表示这条延伸的线段最多能向左、右平移多少格。这样可以找到一个“极大长方形”。遍历所有点,一定可以得到合法的面积最大的长方形。


三 代码

运行结果:
USER: Qi Shen [maxkibb3]
TASK: rectbarn
LANG: C++

Compiling...
Compile: OK

Executing...
   Test 1: TEST OK [0.000 secs, 13052 KB]
   Test 2: TEST OK [0.000 secs, 13052 KB]
   Test 3: TEST OK [0.000 secs, 13052 KB]
   Test 4: TEST OK [0.000 secs, 13052 KB]
   Test 5: TEST OK [0.000 secs, 13052 KB]
   Test 6: TEST OK [0.000 secs, 13052 KB]
   Test 7: TEST OK [0.014 secs, 13052 KB]
   Test 8: TEST OK [0.084 secs, 13052 KB]
   Test 9: TEST OK [0.112 secs, 13052 KB]
   Test 10: TEST OK [0.112 secs, 13052 KB]

All tests OK.

Your program ('rectbarn') produced all correct answers! This is your submission #5 for this problem. Congratulations!


AC代码:
/*
ID:maxkibb3
LANG:C++
PROB:rectbarn
*/

#include<cstdio>
#include<cstring>
#include<algorithm>

const int MAX = 3005;

int R, C, P, Ans;
bool Map[MAX][MAX];
int Up[MAX], Left[MAX], Right[MAX],
	TLeft[MAX], TRight[MAX];

int main() {
	freopen("rectbarn.in", "r", stdin);
	freopen("rectbarn.out", "w", stdout);
	scanf("%d%d%d", &R, &C, &P);
	int x, y;
	while(P--) {
		scanf("%d%d", &x, &y);
		Map[x][y] = true;
	}
	for(int i = 1; i <= C; i++)
		Left[i] = Right[i] = MAX;
	for(int i = 1; i <= R; i++) {
		for(int j = C; j >= 1; j--) {
			if(Map[i][j])
				TRight[j] = 0;
			else
				TRight[j] = TRight[j + 1] + 1;
		}

		for(int j = 1; j <= C; j++) {
			if(Map[i][j]) {
				TLeft[j] = 0;
				Up[j] = 0;
				Left[j] = Right[j] = MAX;
			}
			else {
				TLeft[j] = TLeft[j - 1] + 1;
				Up[j]++;
				Left[j] = std::min(Left[j], TLeft[j]);
				Right[j] = std::min(Right[j], TRight[j]);
			}
			int tmp = (Left[j] + Right[j] - 1) * Up[j];
			Ans = std::max(Ans, tmp);
		}
	}
	printf("%d\n", Ans);
	return 0;
}



您可能感兴趣的与本文相关的镜像

ACE-Step

ACE-Step

音乐合成
ACE-Step

ACE-Step是由中国团队阶跃星辰(StepFun)与ACE Studio联手打造的开源音乐生成模型。 它拥有3.5B参数量,支持快速高质量生成、强可控性和易于拓展的特点。 最厉害的是,它可以生成多种语言的歌曲,包括但不限于中文、英文、日文等19种语言

<think>嗯,用户问的是关于USACO牛棚重建问题。首先,我得回忆一下USACO的题目类型,通常都是算法题,涉及数据结构或者贪心、动态规划之类的。牛棚重建可能是一个具体的题目,我需要先确定题目的大致内容。 可能这个题目是关于安排牛棚的位置,比如有一排牛棚被冲毁,需要重建,然后有一些条件需要满足。比如,可能有N个牛棚的位置,被毁掉了M个,剩下的K个,现在需要选择位置来重建这些牛棚,使得它们之间的最小间距最大化,或者类似的问题。这种情况下,通常会使用二分查找来寻找最大的最小间距,再结合贪心或者排序来处理。 或者题目可能是关于如何用最少的木板覆盖牛棚的破洞,类似经典的区间覆盖问题。比如,给定一定数量的木板,长度固定,如何安排它们来覆盖所有破洞,使得使用的木板最少。这时候可能需要先对破洞的位置进行排序,然后贪心地放置木板,尽可能覆盖更多的破洞。 我需要进一步确认题目的具体描述。比如,假设题目是说,有C头牛,它们的牛棚排列在一条直线上,坐标是x1, x2,...,xC。现在有M个牛棚被毁,需要重建,使得剩下的牛棚之间的最小距离尽可能大。这种情况下,解决方法是先对坐标排序,然后使用二分查找来确定可能的最大最小距离,再检查是否可行。 或者另一个版本是,给定N个牛棚的位置,其中有M个已经损坏,现在要修复其中的S个,使得修复后的牛棚之间的最小距离最大。这时候同样可以用二分答案的方法,每次假设一个最小距离d,然后判断是否能选择至少S个牛棚,使得相邻之间的距离不小于d。 假设用户提到的牛棚重建属于这类问题,那么解题步骤大致是:排序,二分查找可能的d值,然后验证每个d是否可行。验证的方法通常是从左到右选择牛棚,确保相邻之间的距离不小于d,统计可以选的数量是否足够。 另外,可能的变种包括使用动态规划,比如当选择某些位置时,计算最优解。但一般来说,二分答案加贪心的方法在这种最大化最小值的问题中更常见。 需要确保回答的结构清晰,先介绍问题背景,然后分析解题思路,再详细说明步骤,最后给出复杂度分析和可能的代码结构。同时,用户可能需要示例来理解,比如举一个具体的输入例子,说明如何处理。 例如,输入是排序后的牛棚位置:[1, 2, 4, 8, 9],要选择3个,使得最小距离最大。那么可能的d是3,选择1,4,8,间距分别是3和4,满足最小为3。这时候二分的步骤是确定左边界为0,右边界为最大位置差,然后中间值判断是否可行。 同时,要注意可能的边界情况,比如所有牛棚必须被选中,或者只能选两个等。在验证函数中,需要处理这些情况。 最后,代码方面,可以用Python或C++展示,但用户可能需要伪代码或者思路,所以重点放在算法步骤上,而不是具体实现。</think>### USACO 牛棚重建问题解析 #### 问题背景 **牛棚重建**(Barn Repair)是USACO竞赛中的经典问题,属于**贪心算法**的典型应用场景。题目通常描述为: > 在一个直线排列的牛棚序列中,部分牛棚的屋顶损坏。给定有限的木板数量和每块木板的长度限制,要求用最少的木板总长度覆盖所有损坏的牛棚缺口。 #### 核心思路 1. **问题转化** 将损坏的牛棚位置视为离散点,木板的作用是覆盖一段连续区间。关键在于如何用最少的木板总长度覆盖所有缺口。 2. **贪心策略** - 优先覆盖**缺口之间的间隔**较小的区域,以减少木板浪费。 - 通过计算相邻缺口间的距离,优先“跳过”较大的间隔,从而减少木板数量。 --- #### 详细步骤 1. **输入处理** - 获取牛棚总数 `N`、损坏的牛棚数量 `C`、可用木板数量 `M`。 - 记录损坏牛棚的位置,并排序为升序列表 `positions`。 2. **计算间隔** - 计算相邻损坏牛棚之间的间隔,存入列表 `gaps`。 - 例如:损坏位置为 `[3,5,9]`,则间隔为 `[2,4]`。 3. **贪心选择** - 初始情况:使用一块木板覆盖所有损坏牛棚,总长度为 `positions[-1] - positions[0] + 1`。 - 若 `M > 1`,选择最大的 `M-1` 个间隔,将其从总长度中扣除。 - 最终总长度 = 初始总长度 - 前 `M-1` 大间隔之和。 --- #### 示例演示 **输入** ``` N=10, C=5, M=2 损坏位置:3 5 8 9 10 ``` **处理过程** 1. 排序后位置:`[3,5,8,9,10]` 2. 初始总长度:`10-3+1=8`(一块木板覆盖3~10) 3. 计算间隔:`[2,3,1,1]`(对应5-3=2,8-5=3等) 4. 选择最大的 `M-1=1` 个间隔(即3) 5. 最终总长度:`8 - 3 = 5`(分两块木板:3~5 和 8~10) --- #### 复杂度分析 - **时间复杂度**:`O(C log C)`,主要来自排序和间隔排序。 - **空间复杂度**:`O(C)`,存储损坏位置和间隔。 --- #### 代码框架(Python) ```python def main(): # 读取输入 N, M, C = map(int, input().split()) positions = sorted(list(map(int, input().split()))) if M >= C: print(C) # 每个缺口单独一块木板 return # 计算间隔 gaps = [] for i in range(1, C): gaps.append(positions[i] - positions[i-1] - 1) # 间隔=距离-1 # 初始总长度 total_length = positions[-1] - positions[0] + 1 # 减去最大的M-1个间隔 gaps.sort(reverse=True) for i in range(M-1): total_length -= gaps[i] print(total_length) if __name__ == "__main__": main() ``` --- #### 关键点总结 - **贪心选择**:通过扣除最大间隔优化总长度。 - **边界处理**:当木板数量≥损坏牛棚数时,直接返回C。 - **间隔计算**:注意间隔定义为实际距离减1(如位置3和5之间的间隔为1,即4这个位置不需要覆盖)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值