大白P61,空间里有n个点P0,P1,...,Pn-1,把它们两两配对,要求所有的点对距离之和最小。其中n<=20.
分析:dp[s]表示集合s配对后的最小距离之和,状态转移方程为dp[s]=min(dp[s],dp[s^(1<<i)^(1<<j)]+dis(i,j)),其中i<j。
注意这里i是不需要枚举的,因为i最后都是要配对的,无须枚举。
代码:
#include <iostream>
#include <functional>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <map>
#include <stack>
#include <vector>
#include <set>
#include <queue>
#pragma comment (linker,"/STACK:102400000,102400000")
#define pi acos(-1.0)
#define eps 1e-6
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
#define FRE(i,a,b) for(i = a; i <= b; i++)
#define FREE(i,a,b) for(i = a; i >= b; i--)
#define FRL(i,a,b) for(i = a; i < b; i++)
#define FRLL(i,a,b) for(i = a; i > b; i--)
#define mem(t, v) memset ((t) , v, sizeof(t))
#define sf(n) scanf("%d", &n)
#define sff(a,b) scanf("%d %d", &a, &b)
#define sfff(a,b,c) scanf("%d %d %d", &a, &b, &c)
#define pf printf
#define DBG pf("Hi\n")
typedef long long ll;
using namespace std;
#define INF 1<<30
#define mod 1000000009
const int maxn = 1005;
const int MAXN = 2005;
const int MAXM = 200010;
const int N = 1005;
struct Node
{
double x,y;
}node[22];
int n;
double dp[(1<<20)+10];
double Dis(Node a,Node b)
{
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
void solve()
{
int i,j;
int m=1<<n;
for (i=0;i<m;i++) dp[i]=INF;
dp[0]=0;
for (int s=0;s<m;s++)
{
for (i=0;i<n;i++)
if (s&(1<<i)) break;
for (j=i+1;j<n;j++)
{
if (s&(1<<j))
{
dp[s]=min(dp[s],dp[s^(1<<i)^(1<<j)]+Dis(node[i],node[j]));
}
}
}
}
int main()
{
//#ifndef ONLINE_JUDGE
// freopen("C:/Users/lyf/Desktop/IN.txt","r",stdin);
//#endif
int i,j;
while (~scanf("%d",&n))
{
for (i=0;i<n;i++)
scanf("%lf%lf",&node[i].x,&node[i].y);
solve();
printf("%f\n",dp[(1<<n)-1]);
}
return 0;
}