UVA_10911

    这个题目关键在于对分组状态的表示,看了别人的解题报告后发现,由于N很小,所以可以用一个整数的二进制来表示分组状态,该位置为1则代表该队员还未分组,状态转移就是枚举分组的策略就可以了。

    个人感觉用记忆化搜索应该比较好实现一些。

#include<stdio.h>
#include<string.h>
#include<math.h>
#define MAXD 70000
#define MAXN 20
#define INF 1000000000
int N;
double x[MAXN], y[MAXN], f[MAXD];
char b[30];
double sqr(double a, double b)
{
return (a - b) * (a - b);
}
int init()
{
int i;
scanf("%d", &N);
N *= 2;
if(!N)
return 0;
for(i = 0; i < N; i ++)
scanf("%s%lf%lf", b, &x[i], &y[i]);
return 1;
}
double dp(int st)
{
int i, j;
double min = INF, temp;
if(f[st] > -1)
return f[st];
for(i = 0; i < N; i ++)
if((1 << i) & st)
for(j = i + 1; j < N; j ++)
if((1 << j) & st)
{
temp = dp(st ^ (1 << i) ^ (1 << j)) + f[(1 << i) + (1 << j)];
if(temp < min)
min = temp;
}
return f[st] = min;
}
void solve()
{
int i, j;
double res;
f[0] = 0;
for(i = 1; i < (1 << N); i ++)
f[i] = -2;
for(i = 0; i < N; i ++)
for(j = i + 1; j < N; j ++)
f[(1 << i) + (1 << j)] = sqrt(sqr(x[i], x[j]) + sqr(y[i], y[j]));
res = dp((1 << N) - 1);
printf("%.2f\n", res);
}
int main()
{
int t = 0;
while(init())
{
printf("Case %d: ", ++ t);
solve();
}
return 0;
}


posted on 2011-12-02 16:44  Staginner  阅读(514)  评论(0编辑  收藏  举报