您的位置:首页 > 其它

HDU 3362 Fix

2016-02-18 11:22 281 查看
状压DP。

首先很容易想到:一个点要被固定的话,必须有两个已经固定了的点与这个点连边。

再看N的范围,秒想到状压DP,秒出思路。1表示这个点已经被固定,0表示还没被固定。

推导某个状态的时候,枚举一下这个状态下所有被固定的点哪个是最后被固定的,即可得出这个状态的最优解。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;

int n;
struct Point
{
int x;
int y;
int flag;
}p[20];
double dp[600000];
double dis[20][20];
double tmp[20];
int base[20];

bool cmp(const Point&a, const Point&b)
{
return a.flag>b.flag;
}

void read()
{
for (int i = 0; i<n; i++)
scanf("%d%d%d", &p[i].x, &p[i].y, &p[i].flag);
sort(p, p + n, cmp);
}

void init()
{
for (int i = 0; i < (1 << n) + 10; i++) dp[i] = 999999999.0;

for (int i = 0; i<n; i++)
{
for (int j = 0; j<n; j++)
{
if (i == j) dis[i][j] = 999999999.0;
else dis[i][j] = sqrt((p[i].x - p[j].x)*(p[i].x - p[j].x) + (p[i].y - p[j].y)*(p[i].y - p[j].y));
}
}
}

void work()
{
int pos = -1;
for (int i = 0; i<n; i++)
{
if (p[i].flag==1) pos = i;
else break;
}

if (pos == -1) printf("No Solution\n");
else if (pos+1 < 2 )
{
if (n != pos + 1) printf("No Solution\n");
else printf("0.000000\n");
}
else
{
for (int i = 0; i<(1 << (pos + 1)); i++) dp[i] = 0;
for (int i = pos + 1; i<n; i++)
{
int state = (1 << (pos + 1)) - 1 + (1 << i);
for (int k = 0; k <= pos; k++) tmp[k] = dis[i][k];
sort(tmp, tmp + pos + 1);
dp[state] = tmp[0] + tmp[1];
}

for (int i = (1 << (pos + 1)); i<(1 << n); i++)
{
if (dp[i] != 999999999.0) continue;

int temp = i, tot = 0;
while (temp) base[tot++] = temp % 2, temp = temp / 2;

bool fail = 0;
for (int k = 0; k <= pos; k++) if (!base[k]) fail = 1;
if (fail) continue;

for (int k = pos + 1; k < tot; k++)
{
if (base[k])
{
int u = 0;
for (int s = 0; s<tot; s++)
{
if (s == k) continue;
if (base[s]) tmp[u++] = dis[k][s];
}
sort(tmp, tmp + u);
dp[i] = min(dp[i], dp[i - (1 << k)] + tmp[0] + tmp[1]);
}
}
}
printf("%.6lf\n", dp[(1 << n) - 1]);
}
}

int main()
{
while (~scanf("%d", &n))
{
if (!n) break;
read();
init();
work();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: