Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 1893 | Accepted: 523 |
Description
n points are given on the Cartesian plane. Now you have to use some rectangles whose sides are parallel to the axes to cover them. Every point must be covered. And a point can be covered by several rectangles. Each rectangle should cover at least two points including those that fall on its border. Rectangles should have integral dimensions. Degenerate cases (rectangles with zero area) are not allowed. How will you choose the rectangles so as to minimize the total area of them?
Input
The input consists of several test cases. Each test cases begins with a line containing a single integer n (2 ≤ n ≤ 15). Each of the next n lines contains two integers x, y (−1,000 ≤ x, y ≤ 1,000) giving the coordinates of a point. It is assumed that no two points are the same as each other. A single zero follows the last test case.
Output
Output the minimum total area of rectangles on a separate line for each test case.
Sample Input
2 0 1 1 0 0
Sample Output
1
这道题是典型的压缩dp解决问题,复杂的是需要先进行预处理以防止超时。我自己写的代码有些麻烦,参考了其他人的代码进行了修改,利用位运算时压缩dp的一大特点,但是要记住状态的变化要清晰,不然很难查错。
#include<iostream>
#include<cstdio>
#include<algorithm>
#define Max 15
#define MAX 1e9
#define max(a,b) (a<b)?b:a
#define min(a,b) (a<b)?a:b
using namespace std;
int T[Max][Max],A[Max][Max];
int a[Max],b[Max],dp[1<<Max];
int n;
int main()
{
while(scanf("%d",&n)!=EOF){
if(!n) break;
int M=(1<<n)-1;
for(int i=0;i<n;i++)
scanf("%d%d",&a[i],&b[i]);
for(int i=0;i<n;i++)
for(int j=0;j<i;j++){
T[i][j]=0;
int x1=min(a[i],a[j]),x2=max(a[i],a[j]);
int y1=min(b[i],b[j]),y2=max(b[i],b[j]);
for(int k=0;k<n;k++)
if(x1<=a[k]&&a[k]<=x2&&y1<=b[k]&&y2>=b[k])
T[i][j]|=1<<k;
int X=x2-x1?x2-x1:1;
int Y=y2-y1?y2-y1:1;
A[i][j]=A[j][i]=X*Y;
}
dp[0]=0;
for(int N=1;N<=M;N++)
dp[N]=MAX;
for(int N=0;N<=M;N++)
for(int L=0;L<n;L++)
for(int l=0;l<L;l++){
int t=N | T[L][l];
dp[t]=min(dp[t],dp[N]+A[L][l]);
}
printf("%d\n",dp[M]);
}
return 0;
}