题意:给定n(n<=16&&n为偶数)对点的坐标,现在要将他们分成n组,使得每组两个点距离之和加起来最小。。。
解法:
状态压缩,用0 1表示该点是否已经被分配完。。然后记忆化搜索。。。
1 #include<cstdio> 2 #include<cstring> 3 #include<string> 4 #include<iostream> 5 #include<cmath> 6 #include<algorithm> 7 #define N 1<<21 8 #define M 30 9 using namespace std; 10 double x[M],y[M],dis[M][M]; 11 double dp[N]; 12 bool flag[N]; 13 int n; 14 double dfs(int st){ 15 if(flag[st])return dp[st]; 16 flag[st]=1; 17 if(st==0)return dp[st]=0; 18 dp[st]=1e12; 19 for(int i=0;i<n;i++){ 20 if(st&(1<<i)){ 21 for(int j=i+1;j<n;j++){ 22 if(st&(1<<j)){ 23 int next=st; 24 next&=~(1<<i); 25 next&=~(1<<j); 26 dp[st]=min(dp[st],dfs(next)+dis[i][j]); 27 } 28 } 29 } 30 } 31 return dp[st]; 32 } 33 int main(){ 34 string s; 35 int cas=1; 36 while(cin>>n){ 37 if(!n)return 0; 38 n*=2; 39 for(int i=0;i<n;i++) 40 cin>>s>>x[i]>>y[i]; 41 for(int i=0;i<n;i++) 42 for(int j=0;j<n;j++) 43 dis[i][j]=sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])); 44 memset(flag,0,sizeof(flag)); 45 double ans=dfs((1<<n)-1); 46 printf("Case %d: %.2lf\n",cas++,ans); 47 } 48 return 0; 49 }