點集配對問題 集合DP 按位DP

以前就開始看劉汝佳的白皮書了,不過眼高手低,沒有碼過,發現問題好多。於是開始敲一敲。

題意:

空間有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;
}



發佈了59 篇原創文章 · 獲贊 14 · 訪問量 20萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章