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;

}

 

 

 

你可能感兴趣的:(clear)