Uva 10911 Forming Quiz Teams

题意:给定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 }

 

posted @ 2012-12-27 18:30  silver__bullet  阅读(229)  评论(0编辑  收藏  举报