这个题求的用最小的矩形面积把所有的点覆盖,需要注意的是这里的覆盖指的是这些点必须在矩形的边上,然后矩形每次至少要覆盖2个点。需要注意的是共线的时候需要把宽度调整为1,然后剩下的用dp可以解决。DP[i[表示在状态i的时候至少需要多少的面积,i为状态压缩值,把当前已经覆盖的点的状态记录下来。还有一点是2个点构成的矩形要面积最小,那么这2个点一定在角上,所以面积就比较好算了。
这个题我最开始打算枚举状态,然后枚举操作,结果果断TLE。后来直接先预处理所有可能的操作,然后再枚举,就AC了~
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int inf=1<<29;
const int maxn=1<<15;
const int maxm=20;
struct Node
{
int val;
int pos;
Node(){}
Node(int sval,int spos):val(sval),pos(spos){}
}s[300];
int n,dp[maxn],x[maxm],y[maxm],cnt;
int Abs(int x)
{
return x>0?x:-x;
}
void Init()
{
for(int i=0;i<maxn;i++)
dp[i]=inf;
dp[0]=0;
}
bool Onborder(int i,int j,int k)
{
if((x[k]==x[i]||x[k]==x[j])&&y[k]<=max(y[i],y[j])&&y[k]>=min(y[i],y[j]))
return true;
if((y[k]==y[i]||y[k]==y[j])&&x[k]<=max(x[i],x[j])&&x[k]>=min(x[i],x[j]))
return true;
return false;
}
int Area(int i,int j,int &pos)
{
pos|=1<<i;
pos|=1<<j;
for(int k=0;k<n;k++)
if(Onborder(i,j,k))
pos|=1<<k;
if(x[i]==x[j]||y[i]==y[j])
return max(Abs(x[i]-x[j]),Abs(y[i]-y[j]));
return Abs(x[i]-x[j])*Abs(y[i]-y[j]);
}
int main()
{
while(scanf("%d",&n)&&n)
{
cnt=0;
Init();
for(int i=0;i<n;i++)
scanf("%d%d",&x[i],&y[i]);
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
if(i!=j)
{
int pos=0;
int val=Area(i,j,pos);
s[cnt++]=Node(val,pos);
}
for(int i=0;i<maxn;i++)
for(int j=0;j<cnt;j++)
dp[i|s[j].pos]=min(dp[i|s[j].pos],dp[i]+s[j].val);
printf("%d\n",dp[(1<<n)-1]);
}
return 0;
}