【洛谷 P1433】吃奶酪【状压DP】

题目描述

题目
房间里放着 n n n 块奶酪。一只小老鼠要把它们都吃掉,问至少要跑多少距离?老鼠一开始在 ( 0 , 0 ) (0,0) (0,0) 点处。

输入格式
第一行有一个整数,表示奶酪的数量 n n n

2 2 2 到第 ( n + 1 ) (n+1) (n+1) 行,每行两个实数,第 ( i + 1 ) (i+1) (i+1) 行的实数分别表示第 i i i 块奶酪的横纵坐标 x i , y i x i ,y i xi,yi

输出格式

输出一行一个实数,表示要跑的最少距离,保留 2 2 2 位小数。

输入输出样例

输入 #1

4
1 1
1 -1
-1 1
-1 -1

输出 #1

7.41

分析:

状压 D P DP DP( z h e n zhen zhen)( d e de de)( e e e)( x i n xin xin) ! ! ! ! !!!!
f [ i ] [ j ] : f[i][j]: f[i][j] i i i表示是否经过 j j j表示当前走到哪一个点
动态能量转移方程:
f [ i ] [ j ] = m i n ( f [ i ] [ j ] , f [ ( i f[i][j]=min(f[i][j],f[(i f[i][j]=min(f[i][j],f[(i x o r xor xor ( 1 < < j ) ) ] [ k ] + d i s ) (1<<j))][k]+dis) (1<<j))][k]+dis)
d i s dis dis表示 j j j k k k的距离 k k k枚举的是之前经过的点 i i i x o r xor xor ( 1 < < j ) (1<<j) (1<<j)表示将 i i i的第 j j j取反 ( i i i是一个二进制数)
表示第 j j j没经过 (前提是经过 j j j点与第 k k k点) 也就是 i i i j j j k k k位为 1 1 1
学长说复杂度 ⋅ · O ( n O(n O(n2 ∗ * 2 2 2n ) ) )

CODE:

#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
int n;	const double inf=1000000005;  //极致压行
double ans,x[20],y[20],f[1<<16][20];
int main(){
    
    
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%lf%lf",&x[i],&y[i]);
	for(int i=0;i<(1<<16);i++)
		for(int j=1;j<=20;j++)
			f[i][j]=inf;	  //初始化
	f[1][0]=0;x[0]=0;y[0]=0;
	for(int i=1;i<1<<(n+1);i++)
		for(int j=1;j<=n;j++)
			if((i>>j)&1) //经过j
				for(int k=0;k<=n;k++)
					if((i^(1<<j)>>k)&1)  //经过j点与k点
					{
    
    
						double dis=sqrt((x[j]-x[k])*(x[j]-x[k])+(y[j]-y[k])*(y[j]-y[k]));  
						//求j与k之间的距离
						f[i][j]=min(f[i][j],f[(i^(1<<j))][k]+dis);  //DP
					}
	ans=inf;
	for(int i=1;i<=n;i++)
		ans=min(ans,f[(1<<(n+1))-1][i]);
	printf("%.2lf",ans);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/dgssl_xhy/article/details/108123690
今日推荐