hihaCoder1042—跑马圈地(枚举)

题目链接:传送门

时间限制: 10000ms
单点时限: 1000ms
内存限制: 256MB

描述

一觉醒来,小Hi穿越回了古代!由于破敌有功,大汗赏赐小Hi可以在敌人的草原上跑马圈地:一天之内骑马围住的草原以后就是小Hi的牧场。但是令小Hi头疼的是,敌人的草原上有一块臭水塘。小Hi不能骑马走进臭水塘里,并且即使小Hi的骑马路径围住了臭水塘,小Hi的牛马也不能在臭水塘里放牧。


为了更科学地圈地,小Hi对这个问题进行了简化和抽象:(1)敌人的草原是一块n×m的方格矩阵,(2)骑马的路径是沿着方格边缘的一段封闭折线,(3)臭水塘是矩阵中的一块矩形,(4)骑马的路径周长不超过L。小Hi想知道自己最大能圈住多大面积的草原(臭水塘的面积不计入在内)。

如图所示:图1是一条合法的路径;图2也是一条合法的路径,但是圈住的草原面积为0;图3不是合法的路径,因为没有封闭;图4也不是合法的路径,因为穿过了水塘。

输入

第一行3个整数:n, m, L (1 <= n, m <= 100, 1 <= L <= 400)

第二行4个整数:l, r, t, b (0 <= l < r <= m, 0 <= t < b <= n)表示水塘的左、右、上、下边界坐标。

输出

小Hi最大能圈住的面积

样例输入
4 4 8
1 3 1 3
样例输出
3


解题思路:首先我们从某个顶点出发圈出的矩形区域总能获得最大值。我们都用矩形区域去圈取,在上图中的第一种情况下,即最右边和最下边的路径有一部分在黑色区域内,此时我们可以将橙色的线移动变成红色的线,S=S矩-S部分黑。第二种情况下,即最右边或最下边的线在黑色区域内,在图中,我们同样可以将橙色的线右移,但此时还少两条边(未能构成有效路径),若我们剩下能走的距离L'>=2,即S=S矩-S部分黑,若不能走了,则将最下面的橙线向下移动更不可能,只能向上移动,于是变成了情况1。

还有两种情况,都不经过黑色区域,S=S矩,S=S矩-S全部黑(包括了黑色区域),所以我们只要从某顶点开始从小到大枚举所有的矩形区域,然后枚举另外3个顶点,就能得出答案。


#include <cstdio>  
#include <cstring>  
#include <cmath>  
#include <iostream>  
#include <queue>
#include <set>
#include <string>
#include <stack>
#include <algorithm>
#include <map>
#include <bitset>
using namespace std;  
typedef long long ll;
const int N = 1007;
const int M = 11;
const int INF = 0x3fffffff;
const int mod = 1e9+7;
const double Pi = acos(-1.0);
const double sm = 1e-9;

int n,m,L;

int cal( int l , int r , int t , int b )
{
	int ans = 0;
	for( int i = 1 ; i <= m ; ++i ){
		for( int j = 1 ; j <= n ; ++j ){
			int re = 2*i+2*j,s;
			if( re > L ) break;
			if(i<=l||j<=t){
				s = i*j;
			}
			if(i>l&&i<=r&&j>t&&j<=b){
				s = i*j-(i-l)*(j-t);
			}
			if(i>1&&i<r&&j>b){
				if(L>=re+(i-l)*2)
					s = i*j-(b-t)*(i-l);
			}
			if(j>t&&j<b&&i>r){
				if(L>=re+(j-t)*2)
					s = i*j-(r-l)*(j-t);
			}
			if(i>=r&&j>=b){
				s = i*j-(r-l)*(b-t);
			}
			ans = max(ans,s);
		}
	}
	return ans;
}

int main()
{
	while( cin >> n >> m >> L ){
		int l,r,t,b;
		cin >> l >> r >> t >> b ;
		int ans = 0;
		ans = max(ans,cal(l,r,t,b));
		ans = max(ans,cal(m-r,m-l,t,b));
		ans = max(ans,cal(l,r,n-b,n-t));
		ans = max(ans,cal(m-r,m-l,n-b,n-t));
		cout << ans << endl;
	}	
	return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值