题解 P3117 【[USACO15JAN]牛的矩形Cow Rectangles】
暴力什么的就算了,贪心他不香吗
这题其实如果分开想,就三种情况需要讨论:(由于不会发图,只能手打)
1)
5 . . . . .
4 . . . . .
3 . . . H .
2 . . G . .
1 . H . . .
0 1 2 3 4 5
在这种情况下,下面两个H绝对不在一组(因为他们中有G)
2)
5 . . G . .
4 . . H . .
3 . . . H .
2 . H . . .
1 . G . . .
0 1 2 3 4 5
在这种情况下所有H都能拿,因为G在所有H之上/之下
3)
5 . . H . .
4 . . G . .
3 . . . H .
2 . . . . H
1 . H . . .
0 1 2 3 4 5 在这种情况下下面所有H都能拿,但是上面那个连不了(被G挡住了)
因此,我们只需要对这三种情况进行判断就行了(判断方法见注释)
pp find_pair(int aa, int bb){
int mini = 1e8,maxi = 0;
int low = aa, high = bb;
while(cow[low-1].x==cow[aa].x) {low--;if (low==0)break;}
while(cow[high-1].x==cow[bb].x) {high++; if (high == 0) break;}
//这是一个很重要的判断:
//因为我们在排序的时候有可能遇到x相等的点,这个点并不会被搜索,但是这个点仍然需要判断。在这个时候就需要往前和后搜索x相等的点
for (int i=low;i<=high;i++){
if (cow[i].id=='G'){
if (cow[i].y>max(cow[aa].y,cow[bb].y)) mini = min(mini,cow[i].y);
else if (cow[i].y<min(cow[aa].y,cow[bb].y)) maxi = max(maxi,cow[i].y);
else posible = false;
}
}//如果这两个点中间有G就进行以下判断:
//1.如果这个G的y坐标在这两个点的y之上,那么我们将最高值更新
//2.如果这个G的坐标在y之下,我们将最小值之下,我们更新最小值
//3.如果这个G在两个坐标中间,那么这两个点必然不可能选(因为无论怎么样连最后G都会在这个范围里)
return make_pair(mini,maxi);
}
那么问题来了,怎么保证找的G在两个H的中间呢?
还用问吗,加个sort就好了
*注意事项:在找G的时候,我们要记住如果这个G和H的x坐标相等,在sort的时候未必会在他的范围内。那怎么办?
还用问吗,如果x坐标相等就减/加到他不相等为止
while(cow[low-1].x==cow[aa].x) {low--;if (low==0)break;}
while(cow[high-1].x==cow[bb].x) {high++; if (high == 0) break;}
找完G之后,我们对两点之间的所有H进行判断:
如果这个H在上下G的y的范围以内,那么我们更新最大/最小值。(相当于更新高)
pp in_range(int aa, int bb, pp bo){
int maxi = 0,mini = 1e8;
for (int i=aa;i<=bb;i++){
if (cow[i].id!='G'){
if (between(bo,cow[i].y)){
maxi = max(maxi,cow[i].y);
mini = min(mini,cow[i].y);
temp++;
}
}
}//现在已经找出了在这个点上面最低的G点和下面最高的G点
//我们在这个范围里面搜索所以的H,更新最高点和最低点(前提是要在G点的范围内)
return make_pair(maxi,mini);
}
找完之后怎么办?
还用问吗,当然找面积啊
面积 = 底*高 = (x2-x1)*abs(y2-y1) [因为sort了,所以x2一定>=x1]
if (temp){
if(temp>breed){
//如果H的数量大于之前的,直接更新
breed = temp;
ans = abs(res.first-res.second)*abs(cow[j].x-cow[i].x);
}else if (temp==breed) ans = min(ans,abs(res.first-res.second)*abs(cow[j].x-cow[i].x));//否则更新面积(底『x的差』乘高『最高y值和最低y值的差』
}
由于判断不需要储存,这个程序用500的空间其实就够了(800-KB应该够小了吧)
完整代码如下:
#include <iostream>
#include <algorithm>
#include <math.h>
#include <stdio.h>
using namespace std;
#define pp pair<int,int>
struct node{
int x,y;
char id;
}cow[505];
int tot = 0, temp = 0;
int a,b,c; char d;
void add(int aa, int bb, char cc){
cow[++tot].x = aa;
cow[tot].y = bb;
cow[tot].id = cc;
}
bool sorted(node aa, node bb){
return aa.x<bb.x;
}
bool between(pp aa,int b){
return aa.first>b && aa.second<b;
}//这个是表示一个数是否在两个数直接
bool posible = true;
pp find_pair(int aa, int bb){
int mini = 1e8,maxi = 0;
int low = aa, high = bb;
while(cow[low-1].x==cow[aa].x) {low--;if (low==0)break;}
while(cow[high-1].x==cow[bb].x) {high++; if (high == 0) break;}
//这是一个很重要的判断:
//因为我们在排序的时候有可能遇到x相等的点,这个点并不会被搜索,但是这个点仍然需要判断。在这个时候就需要往前和后搜索x相等的点
for (int i=low;i<=high;i++){
if (cow[i].id=='G'){
if (cow[i].y>max(cow[aa].y,cow[bb].y)) mini = min(mini,cow[i].y);
else if (cow[i].y<min(cow[aa].y,cow[bb].y)) maxi = max(maxi,cow[i].y);
else posible = false;
}
}//如果这两个点中间有G就进行以下判断:
//1.如果这个G的y坐标在这两个点的y之上,那么我们将最高值更新
//2.如果这个G的坐标在y之下,我们将最小值之下,我们更新最小值
//3.如果这个G在两个坐标中间,那么这两个点必然不可能选(因为无论怎么样连最后G都会在这个范围里)
return make_pair(mini,maxi);
}
pp in_range(int aa, int bb, pp bo){
int maxi = 0,mini = 1e8;
for (int i=aa;i<=bb;i++){
bool update = true;
while(update){
if (cow[i].id!='G'){
if (between(bo,cow[i].y)){
maxi = max(maxi,cow[i].y);
mini = min(mini,cow[i].y);
temp++;
}
}
}
}//现在已经找出了在这个点上面最低的G点和下面最高的G点
//我们在这个范围里面搜索所以的H,更新最高点和最低点(前提是要在G点的范围内)
return make_pair(maxi,mini);
}
int main(){
ios::sync_with_stdio(0);
cin >> a;
for (int i=0;i<a;i++){
cin >> b >> c >> d;
add(b,c,d);
}
int ans = 0, breed = 1;
sort(cow+1,cow+tot+1,sorted);
//以上不解释
for (int i=1;i<=a;i++){
for (int j=i+breed;j<=a;j++){
if (cow[i].id=='G'||cow[j].id == 'G') continue;//如果两个点中有G就不需要判断
posible = true;
temp = 0;
pp bounds = find_pair(i,j);//先找G的范围
if (!posible) continue;
pp res = in_range(i,j,bounds);//再找H的范围
if (temp){
if(temp>breed){
//如果H的数量大于之前的,直接更新
breed = temp;
ans = abs(res.first-res.second)*abs(cow[j].x-cow[i].x);
}else if (temp==breed) ans = min(ans,abs(res.first-res.second)*abs(cow[j].x-cow[i].x));//否则更新面积(底『x的差』乘高『最高y值和最低y值的差』
}
}
}
cout << breed << endl << ans;
}
你抄任你抄,过得了算我输
题解 P3117 【[USACO15JAN]牛的矩形Cow Rectangles】的更多相关文章
- 洛谷 P1522 牛的旅行 Cow Tours 题解
P1522 牛的旅行 Cow Tours 题目描述 农民 John的农场里有很多牧区.有的路径连接一些特定的牧区.一片所有连通的牧区称为一个牧场.但是就目前而言,你能看到至少有两个牧区通过任何路径都不 ...
- 洛谷 P1821 [USACO07FEB]银牛派对Silver Cow Party 题解
P1821 [USACO07FEB]银牛派对Silver Cow Party 题目描述 One cow from each of N farms (1 ≤ N ≤ 1000) conveniently ...
- Cow Rectangles
Cow Rectangles 题目描述 The locations of Farmer John's N cows (1 <= N <= 500) are described by dis ...
- 洛谷P1522 牛的旅行 Cow Tours
---恢复内容开始--- P1522 牛的旅行 Cow Tours189通过502提交题目提供者该用户不存在标签 图论 USACO难度 提高+/省选-提交该题 讨论 题解 记录 最新讨论 输出格式题目 ...
- 「USACO13MAR」「LuoguP3080」 牛跑The Cow Run (区间dp
题目描述 Farmer John has forgotten to repair a hole in the fence on his farm, and his N cows (1 <= N ...
- 洛谷P1522 [USACO2.4]牛的旅行 Cow Tours
洛谷P1522 [USACO2.4]牛的旅行 Cow Tours 题意: 给出一些牧区的坐标,以及一个用邻接矩阵表示的牧区之间图.如果两个牧区之间有路存在那么这条路的长度就是两个牧区之间的欧几里得距离 ...
- [图论]牛的旅行 Cow Tours :Floyed-Warshall
牛的旅行 Cow Tours 目录 牛的旅行 Cow Tours 题目描述 输入格式 输出格式 输入输出样例 输入 #1 输出 #1 解析 代码 题目描述 农民 John的农场里有很多牧区.有的路径连 ...
- bzoj1648 / P2853 [USACO06DEC]牛的野餐Cow Picnic
P2853 [USACO06DEC]牛的野餐Cow Picnic 你愿意的话,可以写dj. 然鹅,对一个缺时间的退役选手来说,暴力模拟是一个不错的选择. 让每个奶牛都把图走一遍,显然那些被每个奶牛都走 ...
- bzoj1623 / P2909 [USACO08OPEN]牛的车Cow Cars
P2909 [USACO08OPEN]牛的车Cow Cars 显然的贪心. 按速度从小到大排序.然后找车最少的车道,查询是否能填充进去. #include<iostream> #inclu ...
随机推荐
- 十二、React 生命周期函数
React生命周期函数: [官方文档]:https://reactjs.org/docs/react-component.html [定义]组件加载之前,组件加载完成,以及组件更新数据,组件销毁. 触 ...
- 吴裕雄 Bootstrap 前端框架开发——Bootstrap 字体图标(Glyphicons):glyphicon glyphicon-adjust
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name ...
- js基础学习之-js全局对象
声明的三种方式: 第一种: var test; //或var test = 5; 第二种: test = 5; 第三种: window.test; //或window.test = 5; //只是使用 ...
- 《ES6标准入门》(阮一峰)--2.let 和 const 命令
1.let命令 基本用法 let只在命令所在的代码块内(花括号内)有效. for循环的计数器,就很合适使用let命令. //var var a = []; for (var i = 0; i < ...
- tornado反向解析
tornado反向解析 在路由中添加name属性,并且不能使用元组路由,应当由tornado.web.url定义路由. app = tornado.web.Application([ (r'/', I ...
- ZOJ - 3870 Team Formation(异或)
题意:给定N个数,求这N个数中满足A ⊕ B > max{A, B})的AB有多少对.(A,B是N中的某两个数) 分析: 1.异或,首先想到转化为二进制. eg:110011(A)和 1(B)- ...
- Vue 获取时间戳返回自定义时间格式
直接在Vue全局函数定义: Vue.prototype.padLeftZero = function(str) { return ('00' + str).substr(str.length); }; ...
- JS - 局部方法改变全局变量的值
var a = "" function aa() { a="卡卡" } aa() // 注意,aa() 一定要执行,局部赋值全局变量才会有作用 aler ...
- SpringBoot 系列教程之编程式事务使用姿势介绍篇
SpringBoot 系列教程之编程式事务使用姿势介绍篇 前面介绍的几篇事务的博文,主要是利用@Transactional注解的声明式使用姿势,其好处在于使用简单,侵入性低,可辨识性高(一看就知道使用 ...
- 201812-2 小明放学 Java
思路: 红绿灯每种灯亮划分区间,在[0,r]区间内红灯亮,在(r,g+r]区间内绿灯亮,在(r+g,r+g+y]区间内黄灯亮,在划分好区间后只需要判断当小明到达红绿灯时是哪个灯在亮,就可以判断出通过红 ...