hdu 3920 Clear All of Them I

http://acm.hdu.edu.cn/showproblem.php?pid=3920

状态压缩DP.

dp[mask] ,  表示mask二进制表示中为1的元素都被击中的最小代价。当然如果有奇数个1就可以忽略了。

dp[mask | tj | tk] = min( dp[mask | tj | tk] , dp[mask]+dis[j,k] ) ;  ( tj=(1<<(j-1)) , tk=(1<<(k-1)).

如果n=2,有四个元素的时候

0000=> 0011  0101 1001

0011=> 1111

0101=> 1111

1001=> 1111

状态压缩枚举的时候刚好把所有的组合都考虑在里面了=!

 

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string.h>
#include <cmath>
#include <vector>
using namespace std;

struct node
{
	double x;
	double y;
}a[30];

int n, maxint=0;
const int maxn = (1<<20)+10;
const double eps = 1e-8;
const double inf = 2147483647;
double dp[maxn];
double dis[30][30];


double Dist(node p,node q)
{
	return sqrt((p.x-q.x)*(p.x-q.x)+(p.y-q.y)*(p.y-q.y));
}

int main()
{
    int T,ta=1,i=0,j=0,k=0;
	scanf("%d",&T);
	while(T--)
	{
	    scanf("%lf %lf",&a[0].x,&a[0].y);
        scanf("%d",&n);
		for(i=1;i<=2*n;i++)
			scanf("%lf %lf",&a[i].x,&a[i].y);

		maxint = (1<<(2*n))-1;

		for(i=0;i<=2*n;i++)
			for(j=i;j<=2*n;j++)
				dis[j][i]=dis[i][j]=Dist(a[i],a[j]);

		for(i=1;i<=maxint;i++)
			dp[i]=inf;
        dp[0]=0;
		for(i=0;i<=maxint;i++)
		{
		    if(dp[i]==inf)
				continue;
			int tj=0;
            for(j=1;j<=2*n;j++)
			{
				tj=(1<<(j-1));
				if( (tj & i)==0)
                   break;
			}
			if(tj==0)
				break;

			for(k=j+1;k<=2*n;k++)
			{
				int tk = 1<<(k-1);
				if( (tk & i)==0)
				{
					int tmp=(i|tj|tk);
				    dp[tmp]=min(dp[tmp],dp[i]+dis[j][0]+dis[j][k]);
                    dp[tmp]=min(dp[tmp],dp[i]+dis[k][0]+dis[j][k]);
				}
			}
		}
		printf("Case #%d: %.2f\n",ta++,dp[maxint]);
	}
	return 0;
}
 

 

 

posted on 2011-08-22 02:16  lwbaptx  阅读(229)  评论(0编辑  收藏  举报

导航