题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3362
题目大意:给出n(n<=18)个点的坐标,某些点固定了,某些点没固定,要求加一些边使得没固定的点变成固定,求最小花费。
思路:n比较小可用状压DP,从所给的起始状态开始DP,每个状态里面都枚举一个未固定的点然后通过找两个已经固定的点更新另一个状态,dp保存最优值即可。
Code:
/* W w w mm mm 222222222 7777777777777 */
/* W w w w m m m m 222 22 7777 */
/* w w w w m m m m 22 777 */
/* w w w w m m m m 22 77 */
/* w w w w m m m m 222 77 */
/* w w w w m m m m 222 77 */
/* w w w w m m m m 222 77 */
/* w w w w m m m m 222 77 */
/* w w w w m m m m 222 77 */
/* ww ww m mm m 222222222222222 77 */
//#pragma comment(linker, "/STACK:102400000,102400000")
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
int n;
const int N=20;
const int maxn=300005;
double dist[20];
int st,en;
struct Point
{
double x,y;
int c;
}a[N];
double dp[maxn];
void init()
{
for(int i=0;i<(1<<n);i++)
{
dp[i]=-1;
}
}
void debug()
{
for(int i=st;i<(1<<n);i++)
{
printf("dp[%d]=%f\n",i,dp[i]);
}
}
void debug_dist()
{
for(int i=1;i<=n;i++)
{
printf("dist[%d]=%f\n",i,dist[i]);
}
}
double dis(int i,int j)
{
return sqrt((a[i].x-a[j].x)*(a[i].x-a[j].x)
+(a[i].y-a[j].y)*(a[i].y-a[j].y));
}
void solve()
{
st=0;
for(int i=1;i<=n;i++)
{
if(a[i].c)
{
st+=1<<(i-1);
}
}
dp[st]=0;
//printf("st=%d\n",st);
en=(1<<n)-1;
for(int i=st;i<=en;i++)
{
if(dp[i]<0)
{
continue;
}
for(int j=1;j<=n;j++)
{
if(!(i&(1<<(j-1))))
{
//printf("i=%d j=%d\n",i,j);
int cnt=0;
for(int p=1;p<=n;p++)
{
if((i&(1<<(p-1))))
{
//printf("p=%d\n",p);
dist[cnt++]=dis(j,p);
//printf("%f\n",dis(j,p));
}
}
if(cnt<2)continue;
//debug_dist();
sort(dist,dist+cnt);
int S=i+(1<<(j-1));
if(dp[S]<0)
{
dp[S]=dp[i]+dist[0]+dist[1];
}
else
{
dp[S]=min(dp[S],dp[i]+dist[0]+dist[1]);
}
//debug_dist();
}
}
}
}
int main()
{
#ifdef ONLINE_JUDGE
#else
freopen("test.in","r",stdin);
#endif
while(~scanf("%d",&n))
{
if(!n)break;
for(int i=1;i<=n;i++)
{
scanf("%lf%lf%d",&a[i].x,&a[i].y,&a[i].c);
}
init();
solve();
//debug();
if(dp[(1<<n)-1]<0)
{
printf("No Solution\n");
}
else
{
printf("%.6f\n",dp[(1<<n)-1]);
}
}
return 0;
}
本文介绍了一种使用状态压缩动态规划(状压DP)的方法来解决一个经典的算法问题。该问题要求在给定若干个点的情况下,通过连接边的方式使所有非固定的点变得固定,并寻求完成这一目标所需的最小代价。
1万+

被折叠的 条评论
为什么被折叠?



