状态dp
讲15个点描述成2^15个状态
枚举出15*14/2个矩形所能覆盖的点
然后状态转移就是每个矩形往上面贴
这里边比较麻烦的一点就是如果两个点的横左边或者纵坐标相同,这样它本身不会确定一个矩形
所以就要枚举两个宽为1的矩形,这样使得编写麻烦了很多
后边仔细想了想,其实只要出现这种情况的时候认为只有这两个点能被包围就行了,原因自己想想就明白了
代码是后边的想法的代码
#include <iostream>
#include<stdio.h>
#include<string.h>
#include<math.h>
using namespace std;
int x[20],y[20];
int f[1000],are[1000];
const int inf=9999999;
int swap(int &a,int &b)
{
if(a>b)
{
int tmp=a;
a=b;
b=tmp;
}
return
0;
}
int que[1000001];
int ans[40000],text[40000];
int main()
{
while(1)
{
int n;
scanf("%d",&n);
if(!n) break;
for(int i=1;i<=n;i++)
scanf("%d %d",&x[i],&y[i]);
int time=0;
memset(are,0,sizeof(are));
memset(f,0,sizeof(f));
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
{
if(x[i]!=x[j]&&y[i]!=y[j])
{
are[++time]=fabs(x[i]-x[j])*fabs(y[i]-y[j]);
int tmp1=x[i],tmp2=x[j];
int txt1=y[i],txt2=y[j];
swap(tmp1,tmp2);
swap(txt1,txt2);
for(int k=1;k<=n;k++)
{
if(x[k]>=tmp1&&x[k]<=tmp2)
if(y[k]>=txt1&&y[k]<=txt2)
f[time]+=1<<(k-1);
}
}
else
{
are[++time]=fabs(x[i]-x[j]);
are[time]+=fabs(y[i]-y[j]);
f[time]+=1<<(i-1);
f[time]+=1<<(j-1);
}
}
int front=1,end=1;
que[front]=0;
for(int
i=1;i<=1<<n;i++)
ans[i]=inf;
ans[0]=0;
memset(text,0,sizeof(text));
text[0]=1;
while(front<=end)
{
int tmp=que[front++];
text[tmp]=0;
for(int i=1;i<=time;i++)
if(ans[tmp|f[i]]>ans[tmp]+are[i])
{
ans[tmp|f[i]]=ans[tmp]+are[i];
if(!text[tmp|f[i]])
{
text[tmp|f[i]]=1;
que[++end]=tmp|f[i];
}
}
}
printf("%d\n",ans[(1<<n)-1]);
}
return
0;
}