题目:http://poj.org/problem?id=2836
在一个二位平面内,有一些点,请用一些矩形来覆盖这些点,保证每个点至少被一个矩形覆盖,求矩形面积和的最小值。
因为要最小,所以每个矩形的一条对角线的两个顶点肯定是这些点,所以可以枚举出以i,j为顶点的矩形可以覆盖的集合,以及它的面积。需要注意的是,比如(1,1),(2,1),(3,1),(1,10)这组数据,很显然我们希望(1,1),(2,1),(3,1)被一个矩形覆盖,(1,10)被一个覆盖,但这时发现这两个矩形的面积好像都是0,这肯定是不行的,所以当我们想要覆盖的点在一条直线上时,应该把覆盖他们的矩形的宽置为1.
int n;
int a[20],b[20];
int all;
int dp[(1<<15)+5];
int Area[(1<<15)+5];
int res[(1<<15)+5],cnt;
inline void init(){
clr(Area);
rep(i,0,n){
rep(j,i+1,n){
int st=0;
int x1=min(a[i],a[j]),x2=max(a[j],a[i]),y1=min(b[i],b[j]),y2=max(b[i],b[j]);
int area;
if(x2==x1) area=y2-y1;
else if(y2==y1) area=x2-x1;
else area=(x2-x1)*(y2-y1);
rep(k,0,n){
if(a[k]>=x1 && a[k]<=x2 && b[k]>=y1 && b[k]<=y2){
st |= (1<<k);
}
}
res[cnt++]=st;
Area[st]=area;
}
}
}
int main(){
while(1){
n=input();
if(n==0) break;
rep(i,0,n) a[i]=input(),b[i]=input();
all=(1<<n);
cnt=0;
init();
rep(i,0,all) dp[i]=INF;
dp[0]=0;
rep(i,0,all){
if(dp[i]!=INF){
rep(j,0,cnt){
int jj=res[j];
if(Area[jj]!=-1){
int val=(i|jj);
dp[val]=min(dp[val],dp[i]+Area[jj]);
}
}
}
}
output(dp[all-1]);
}
return 0;
}