POJ

来源:互联网 发布:什么是linux内核 编辑:程序博客网 时间:2024/05/21 19:30

传送门:POJ2836

题意:坐标平面上有n各点,用任意大小(非零)的矩形覆盖它们,每个矩形至少覆盖两个点,矩形边长为正整数,求最少所需要的矩形的总面积。

思路:先将平面上任意两个点组成的矩形预处理出来,并将每个矩形内部包含的点的状态压成一个整数,然后进行dp,dp[s]表示覆盖的点集状态为s的最小面积,枚举每个预处理出来的矩形进行转移就好了。

代码:

#include<iostream>#include<string.h>#include<algorithm>#define ll long long#define pb push_back#define fi first#define se second#define pi acos(-1)#define inf 0x3f3f3f3f#define lson l,mid,rt<<1#define rson mid+1,r,rt<<1|1#define rep(i,x,n) for(int i=x;i<n;i++)#define per(i,n,x) for(int i=n;i>=x;i--)using namespace std;typedef pair<int,int>P;const int MAXN=100010;int gcd(int a,int b){return b?gcd(b,a%b):a;}struct node{int id, area;node(){}node(int _id, int _area) : id(_id), area(_area){}}rec[300];P p[20];// 判断k是否在i,j组成的矩形里 bool inside(int i, int j, int k){return ((p[i].fi - p[k].fi) * (p[j].fi - p[k].fi) <= 0) && ((p[i].se - p[k].se) * (p[j].se - p[k].se) <= 0);}int dp[1 << 16]; int main(){int n;while(cin >> n, n){for(int i = 0; i < n; i++){cin >> p[i].fi >> p[i].se;}node t;int cnt = 0;for(int i = 0; i < n; i++){for(int j = i + 1; j < n; j++){t.id = 0;t.area = max(1, abs(p[i].fi - p[j].fi)) * max(1, abs(p[i].se - p[j].se));t.id |= 1 << i;t.id |= 1 << j;for(int k = 0; k < n; k++){if(inside(i, j, k))t.id |= 1 << k;}rec[cnt++] = t;}}memset(dp, inf, sizeof(dp));dp[0] = 0;for(int i = 0; i < cnt; i++){for(int j = 0; j < (1 << n); j++){dp[rec[i].id | j] = min(dp[rec[i].id | j], dp[j] + rec[i].area);}}cout << dp[(1 << n) - 1] << endl;} return 0;}


原创粉丝点击