時間限制: 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 81 3 1 3
範例輸出
3
分析:這道題不太能想到,就是把複雜問題簡單化,可以看出,有很多種覆蓋的情況,無非是不覆蓋,覆蓋一個角,兩個,全覆蓋。當覆蓋兩個角的時候可以看出是缺邊的。這樣必須讓面積再次縮小,否則周長不夠,可以不用考慮。而覆蓋一個角的時候周長是可以沿著水塘一遍的,正好周長夠了,無非是面積小了點。全覆蓋的話就是顯然的了。
痛點在于思路有了如何去實現。
這裡用到了一個轉化的思想,就是水塘在草原裡實際上是有所側重的(位置),而為了統一,我們把所有水塘偏向的情況都統一放在右下角的方位處,然後枚舉就可以了。具體代碼如下:
#include<iostream>#include<stdio.h>using namespace std;int main(){ int n,m,L,l,r,t,b,l1,r1,t1,b1; int ans=0; scanf("%d%d%d",&n,&m,&L); scanf("%d%d%d%d",&l,&r,&t,&b); if(l+r<=m&&t+b<=n)//這樣說明偏向哪側。自拿執行個體驗證 { l1=m-r; r1=m-l; t1=n-b; b1=n-t; } else if(l+r<=m&&t+b>n) { l1=m-r; r1=m-l; t1=t; b1=b; } else if(l+r>m&&t+b<=n) { l1=l; r1=r; t1=n-b; b1=n-t; }//剩下的一種情況本身就已經是右下角了 for(int i=0;i<=L/2&&i<=n;i++)//依次枚舉 { for(int j=0;j<=L/2&&j<=m&&i+j<=L/2;j++) { if(i<=t1||j<=l1)//這種情況就是不經過水塘的 ans=max(ans,i*j); if(i>t1&&i<=b1&&j>l1&&j<=r1)//正好經過水塘一個角 ans=max(ans,i*j-(i-t1)*(j-l1)); if(i>b1&&j>r1)//全覆蓋 ans=max(ans,i*j-(b1-t1)*(r1-l1)); } } printf("%d",ans); return 0;}