最优配对问题

UvaOJ10911


  这个题首先要明确  1.二进制的枚举特点

                                  2. ^ 运算符的特点



   1. 二进制枚举较多见,书上的代码是这样的

       递推 是由 dp[ S ]  是 0 到 log S + 1(以2 为底) 个点集合组成的最小距离。

       S  表示的是 点 i ,j 的组合种类  转换成二进制表示为 S = (1<<i)+ (1<<j) 

      所以通过枚举 S 就 能确定  i,j 的组合是那种。

      dp[s] = min(dp[s] , dist(i,j) + dp[s ^ (1<<i) ^(1<<j)]);

    2.   ^ 表示异或, 0^1 = 1, 1^1 = 0 , 相异为1

          则 a^a = 00000

          同理 S本身枚举的就是两个点的之和, s^(1<<i) 就相当于s中原有的(1<<i) 再异或一个(1<<i) 那就说明去除了这个点,同理有异或(1<<j),有去除了j这个点。剩余的s表示的就是  剩下的点的集合了。那么dp[s] 就是剩下点集合的最小距离和。

       

for(s = 1;s< (1<<n );s++)
		{
			dp[s] = INF;
			for(i = 0;i<n;i++)
			if(s & (1<<i))break;

			for(j=i+1;j<n;j++)
			if(s & (1<<j))
			{
				dp[s] = min(dp[s] ,dist(i,j) + dp[s ^ (1<<i) ^(1<<j)]);
			}
		
		}

  

#include<stdio.h>
#include<string.h>
#include<math.h>
#define min(a,b) a<b?a:b
#define INF 1<<30
int na[20][2];
double dp[100000];

double dist(int i,int j)
{
	return sqrt( (na[i][0]-na[j][0])*(na[i][0]-na[j][0]) + (na[i][1]-na[j][1])*(na[i][1]-na[j][1]));
}
int main()
{
	int n,s;
	int i,j,count = 1;
	char a[100];
	while(scanf("%d",&n))
	{
		getchar();
		if(n== 0)break;

		for( i = 0;i< 2*n ;i++)
		{
			scanf("%s %d %d",&a,&na[i][0],&na[i][1]);
		}
		
		n= 2*n;

		
	    dp[0] = 0;
		for(s = 1;s< (1<<n );s++)
		{
			dp[s] = INF;
			for(i = 0;i<n;i++)
			if(s & (1<<i))break;

			for(j=i+1;j<n;j++)
			if(s & (1<<j))
			{
				dp[s] = min(dp[s] ,dist(i,j) + dp[s ^ (1<<i) ^(1<<j)]);
			}
		
		}


		printf("Case %d: %.2f\n",count++,dp[ (1<<n) - 1 ]);
	}



	return 0;
}

     http://www.cnblogs.com/pangblog/archive/2013/09/21/3331303.html

    这位大神用的是深搜 感觉也不错!                

    原文作者:舞伴问题
    原文地址: https://blog.csdn.net/sinat_26019265/article/details/51291331
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞