jzoj 3420 最优配对问题

Description

平面上有n个点P1,P2,…,Pn,你的任务是把它们配成n/2对(n是偶数),使得每个点恰好在一个点对中。所有点对中两点的距离之和应尽量小。n<=20,|xi|,|yi|<=10000。

Input

第一行输入n(2到20之间的偶数)
接下来n行,每行输入两个整数表示xi,yi。|xi|,|yi|<=10000。

Output

输出最小配对距离。答案保留两位小数。

Sample Input

4

8730 9323

-3374 3929

-7890 -6727

1257 4689

Sample Output

20366.60

Data Constraint

2<=N<=20

Solution

从这题开始状压的学习。
发现这个数据范围很小,考虑用二进制进行状压。
设一个状态f[i],表示把i转化为二进制之后,为1的位已配对好,所得的最大值。
强制选编号小的与编号大的进行配对。
每次枚举一个i
找到i中为1的第一位,设为x 另外再枚举一个y
则可得f[i]=max(f[i],f[i^((1<<(x-1))^(1<<(y-1)]+dis(x,y));

Code

#include 
#include 
#include 
#include 
#define inf 1000000007
#define fo(i,a,b) for (i=a;i<=b;i++) 
using namespace std;
double f[2000000];
int x[25],y[25];
double dis(int i,int j) {return sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
}
int main(){//freopen("1.in","r",stdin);//freopen("1.out","w",stdout);int n,i,j;scanf("%d",&n);fo(i,1,n) scanf("%d%d",&x[i],&y[i]);fo(i,1,((1<1)) {f[i]=inf;for (j=1;j<=n;j++) if ((i&(1<<(j-1)))!=0) break;for (int k=j+1;k<=n;k++) if ((i&(1<<(k-1)))!=0)f[i]=min(f[i],f[i^(1<<(j-1))^(1<<(k-1))]+dis(k,j));
}printf("%.2lf",f[(1<1]);
} 


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部