点集配对问题 集合DP 按位DP


此页面通过工具从 csdn 导出,格式可能有问题。

以前就开始看刘汝佳的白皮书了,不过眼高手低,没有码过,发现问题好多。于是开始敲一敲。

题意:

空间有n个点,分成n/2对,使得所有点集的两点之间的距离之和最小。

d(s) = min{ d(s-i-j) }    i,j 属于 s

PS:只有20个点,每个点可以取可以不取,所以用20位的二进制数来表示每个状态。

要注意的是,i,j  是不需要一个一个都枚举的,会有重复。比如1234会有12+34,又会有34+12造成浪费。如果是123456就会浪费更多。可以假设最小的1是当前取得,那么只要 找 12,13,14,15,16 。

#include <cstdio>
#include <cmath>
#include <iostream>
using namespace std;
typedef struct{
	int x,y,z;
}NODE;
NODE g[22];
int n,k;
double d[1<<22];
double dis(int i,int j){
	NODE a(g[i]), b(g[j]);
	return sqrt(((double)(a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)+(a.z-b.z)*(a.z-b.z)));
}
int main(){
	cin >> n;
	for (int i(0);i<n;i++)
		cin >> g[i].x >> g[i].y >> g[i].z;
	for ( int i(1);i<(1<<n);i++){
		d[i] = 1e10;
		int k;
		for (k=0;k<n;k++)
			if (  i & (1<<k) ) break;
		for (int j(k+1);j<n;j++)
			if (i & (1<<j))
				d[i] = min(d[i],dis(k,j)+d[i^(1<<j)^(1<<k)]);
	}
	cout << d[(1<<n)-1] << endl;
	return 0;
}



Avatar
huiren
Code Artisan

问渠那得清如许,为有源头活水来

下一页
上一页
comments powered by Disqus