1. 程式人生 > >HDU - 5128The E-pang Palace+暴力枚舉,計算幾何

HDU - 5128The E-pang Palace+暴力枚舉,計算幾何

err AS RR with 計算 min Go span PQ

第一次寫計算幾何,ac,感動。

不過感覺自己的代碼還可以美化一下。

傳送門:http://acm.hdu.edu.cn/showproblem.php?pid=5128

題意:

在一個坐標系中,有n個點,從中找到兩個互不touch,互不cross的兩個矩形(邊要和坐標軸平行),使得面積最大。

思路:

枚舉每個點,n的四次方,這題有個坑點是“回型矩陣”,是真的坑,然後discuss區裏說的十字形矩陣是騙人的。

每次對枚舉的四個點進行check,如果兩個矩陣的四個點相互不在對方的矩陣中,那麽這組就是合法的。

如果(這四個點組成一個回型矩陣),那麽上面判check的結果就是,*一個矩陣的四個點在另一個矩陣中,而另一個矩陣沒有*。

註意**中的條件是必要條件,還有判斷一下,這個回型矩陣中,有沒有邊重合。

ac代碼

技術分享圖片
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <list>
#include 
<iterator> #include <cmath> using namespace std; #define lson (l , mid , rt << 1) #define rson (mid + 1 , r , rt << 1 | 1) #define debug(x) cerr << #x << " = " << x << "\n"; #define pb push_back #define pq priority_queue #define Pll pair<ll,ll> #define
Pii pair<int,int> #define fi first #define se second #define OKC ios::sync_with_stdio(false);cin.tie(0);cout.tie(0) typedef long long ll; typedef unsigned long long ull; /*-----------------show time----------------*/ int n; int l[40],r[40]; int mp[205][205]; bool check(int i,int j,int x,int y) { int e[5][4]; e[1][1] = l[i],e[1][2] = r[i]; e[2][1] = l[i],e[2][2] = r[j]; e[3][1] = l[j],e[3][2] = r[j]; e[4][1] = l[j],e[4][2] = r[i]; int le1 = min(l[x],l[y]),le2 = max(l[x],l[y]); int ri1 = min(r[x],r[y]),ri2 = max(r[x],r[y]); if(mp[l[x]][r[y]]==0||mp[l[y]][r[x]]==0)return false; for(int w=1; w<=4; w++) { if(mp[e[w][1]][e[w][2]]==0)return false; if(e[w][1]>=le1 && e[w][1] <= le2 && e[w][2]>=ri1 && e[w][2] <= ri2) return false; } return true; } /* bool tepan(int i,int j,int q,int w) { //1 int l1 = min(l[i],l[j]),l2 = max(l[i],l[j]); int r1 = min(r[i],r[j]),r2 = max(r[i],r[j]); //2 int x1 = min(l[q],l[w]),x2 = max(l[q],l[w]); int y1 = min(r[q],r[w]),y2 = max(r[q],r[w]); if(y1<r1 && y2>r2 && l1<x1 && l2 > x2)return true; if(y1>r1 && y2<r2 && l1>x1 && l2 < x2)return true; return false; } */ int main(){ while(~scanf("%d", &n)&&n){ memset(mp,0,sizeof(mp)); for(int i=1; i<=n; i++){ scanf("%d%d", &l[i],&r[i]); mp[l[i]][r[i]] = 1; } int ans = 0; for(int i=1; i<=n; i++){ for(int j=1; j<=n; j++){ for(int q = 1; q<=n; q++){ for(int w = 1; w<=n; w++){ if(check(i,j,q,w)&&check(q,w,i,j)){ //if(tepan(i,j,q,w) ||tepan(q,w,i,j))continue; if(l[i]==l[j]||r[i]==r[j]||l[q]==l[w]||r[q]==r[w])continue; int tmp = abs(l[i]-l[j]) * abs(r[i] - r[j]) + abs(l[q]-l[w]) * abs(r[q] - r[w]) ; ans = max (ans,tmp); } else if(check(i,j,q,w)) { if(l[i]==l[j]||r[i]==r[j]||l[q]==l[w]||r[q]==r[w])continue; if(mp[l[q]][r[w]]==0||mp[l[w]][r[q]]==0)continue; int tmp = abs(l[i]-l[j]) * abs(r[i] - r[j]) ; // int tmp = max(tmp,) int e[5][4]; e[1][1] = l[q],e[1][2] = r[q]; e[2][1] = l[q],e[2][2] = r[w]; e[3][1] = l[w],e[3][2] = r[w]; e[4][1] = l[w],e[4][2] = r[q]; int le1 = min(l[i],l[j]),le2 = max(l[i],l[j]); int ri1 = min(r[i],r[j]),ri2 = max(r[i],r[j]); int flag = 1; for(int s = 1; s<=4;s++){ //用於判斷回字型的合法,裏面完全包於 if(e[s][1]==le1||e[s][1]==le2||e[s][2]==ri1||e[s][2]==ri1){ flag = 0; break; } } if(flag)ans = max (ans,tmp); /* if(tmp==3) //樣例一自己跑出3.發現了回型矩陣的奧秘; { cout<<"----------------"<<endl; cout<<"zhe;"<<i<<" "<<j<<" "<<q<<" "<<w<<endl; int e[5][4]; e[1][1] = l[i],e[1][2] = r[i]; e[2][1] = l[i],e[2][2] = r[j]; e[3][1] = l[j],e[3][2] = r[j]; e[4][1] = l[j],e[4][2] = r[i]; int le1 = min(l[q],l[w]),le2 = max(l[q],l[w]); int ri1 = min(r[q],r[w]),ri2 = max(r[q],r[w]); debug(le1);debug(le2);debug(ri1);debug(ri2); } */ } }}}} //這是四重循環的右括號 if(ans == 0)puts("imp"); else printf("%d\n",ans); } return 0; }
HDU5128

HDU - 5128The E-pang Palace+暴力枚舉,計算幾何