题目描述
给定一些点的坐标,要求求能够覆盖所有点的最小面积的矩形,输出所求矩形的面积和四个顶点坐标
输入输出格式
输入格式:
第一行为一个整数n(3<=n<=50000),从第2至第n+1行每行有两个浮点数,表示一个顶点的x和y坐标,不用科学计数法
输出格式:
第一行为一个浮点数,表示所求矩形的面积(精确到小数点后5位),接下来4行每行表示一个顶点坐标,要求第一行为y坐标最小的顶点,其后按逆时针输出顶点坐标.如果用相同y坐标,先输出最小x坐标的顶点
输入输出样例
输入样例#1: 复制
6 1.0 3.00000 1 4.00000 2.0000 1 3 0.0000 3.00000 6 6.0 3.0
输出样例#1: 复制
18.00000 3.00000 0.00000 6.00000 3.00000 3.00000 6.00000 0.00000 3.00000
说明
感谢 @intruder 提供题目简述
这道题想着简单,写着有毒。我们先做一个凸包,然后旋转卡壳。这个旋转卡壳需要卡3个点:以当前直线为下边的上左右边界,每一次旋转我们同时处理移动三个点就行了。这样我们带一个大常数就可以卡出所有可能最优的矩形。关于旋转卡壳可以看这一篇博客:我不是“这篇博客”o(>﹏<)o
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
using namespace std;
const int maxn=11;
LL dp[2][1<<(maxn+1)];
int n,m,i,j,now,news;//n行m列
bool getbit(int num,int k){ //从第0开始
return num&(1<<k);
}
void editbit(int & num,int k,bool val){
int ret;
ret=num-(getbit(num,k)<<k)+(val<<k);
num=ret;
}
int rt(int num){
return (num>>=1);
}
int main(){
while(1){
memset(dp,0,sizeof(dp));
scanf("%d%d",&n,&m);
if(n==0 && m==0) break;
if(n>m) swap(n,m);
int ini=(1<<n)-1;editbit(ini,n-1,0);
dp[0][ini]=1, now = 0;
for(register int i=0;i<m;i++)
for(register int j=0;j<n;j++){
if(i==0 && j==0) continue;
now ^= 1;
memset(dp[now], 0, sizeof(dp[now]));
for(register int k=0;k<1<<n;k++){
if(getbit(k,0)==0)
news=k>>1,editbit(news,n-1,1),dp[now][news]+=dp[now ^ 1][k];
if((getbit(k,0)==1 || i==0) && (getbit(k,n-1)==0 && j!=0))
news=k>>1,editbit(news,n-2,1),editbit(news,n-1,1),dp[now][news]+=dp[now ^ 1][k];
if(getbit(k,0)==1 || i==0)
news=k>>1,dp[now][news]+=dp[now ^ 1][k];
}
}
printf("%lld\n",dp[now][(1<<n)-1]);
}
return 0;
}
rockdu
没有帐号? 立即注册