1. 程式人生 > >Forming Quiz Teams (狀壓dp,最優配對問題)

Forming Quiz Teams (狀壓dp,最優配對問題)

You have been given the job of forming the quiz teams for the next ‘MCA CPCI Quiz Championship’. There are 2 ∗ N students interested to participate and you have to form N teams, each team consisting of two members. Since the members have to practice together, all the students want their members house as near as possible. Let x1 be the distance between the houses of group 1, x2 be the distance betweenthehousesofgroup2andsoon. Youhavetomakesurethesummation(x1+x2+x3+...+xn) is minimized.

Input

There will be many cases in the input file. Each case starts with an integer N (N ≤ 8). The next 2 ∗ Nlines will given the information of the students. Each line starts with the students name, followed by the x coordinate and then the y coordinate. Both x,y are integers in the range 0 to 1000. Students name will consist of lowercase letters only and the length will be at most 20.

Input is terminated by a case where N is equal to 0.Output

For each case, output the case number followed by the summation of the distances, rounded to 2 decimal places. Follow the sample for exact format.

Sample Input

5
sohel 10 10
mahmud 20 10
sanny 5 5
prince 1 1
per 120 3
mf 6 6
kugel 50 60
joey 3 24
limon 6 9
manzoor 0 0
1
derek 9 9
jimmy 10 10
0

Sample Output

Case 1: 118.40
Case 2: 1.41

題意:給你幾個點(2*n)的座標,現在想把這些點分為n對,使得n對的距離和最小。

題解:狀壓dp,dp[S]表示狀態S裡面所有點互相配對的最小值,狀態轉移方程:dp[S] = min{dis[i][j] + dp[S^(1<<i)^(1<<j)},i表示狀態S裡面的最大點,j表示狀態S裡面小於i的點。解釋一下,因為i必須要一個小於它的匹配點,所以dp[S]就該等於取出i,j點的狀態dp[S']加上dis[i][j],由此也可知道,當狀態S其中的點為奇數的時候,dp[S]就不存在。

//#include"bits/stdc++.h"
//#include<unordered_map>
//#include<unordered_set>
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<set>
#include<vector>
#include<bitset>
#include<climits>
#include<queue>
#include<iomanip>
#include<cmath>
#include<stack>
#include<map>
#include<ctime>
#include<new>
using namespace std;
#define LL long long
#define ULL unsigned long long
#define MT(a,b) memset(a,b,sizeof(a))
#define lson l, mid, node << 1
#define rson mid + 1, r, node << 1 | 1
const int INF  =  0x3f3f3f3f;
const int O    =  1e5;
const int mod  =  1e4 + 7;
const int maxn =  1e6+5;
const double PI  =  acos(-1.0);
const double E   =  2.718281828459;

double dp[1<<21];
int main(){
    int n, l = 0;
    while(~scanf("%d", &n) && n){
        n *= 2;
        double x[100], y[100];
        for(int i=0; i<n; i++) {
            char s[100]; scanf("%s %lf%lf", s, &x[i], &y[i]);
        }
        
        double dis[100][100];
        for(int i=0; i<n; i++) for(int j=0; j<n; j++)
            dis[i][j] = sqrt((x[i]-x[j])*(x[i]-x[j]) + (y[i]-y[j])*(y[i]-y[j]));
        
        dp[0] = 0;
        for(int S=1; S<(1<<n); S++){
            dp[S] = INF;
            int i =0, cnt = 0;
            for(int j=0; j<n; j++) if(S & (1<<j)) { i = j; cnt ++; }
            if(cnt & 1) continue;
            for(int j=0; j<i; j++) if(S & (1<<j))
                dp[S] = min(dp[S], dis[i][j] + dp[S^(1<<i)^(1<<j)]);
        }
        double ans = dp[(1<<n)-1];
        printf("Case %d: %.2f\n", ++l, ans);
    }
    return 0;
}