P1433 吃奶酪 题解 状态压缩 DP

日常深夜更博 又是因为把n写成了数字找bug找了半天 哭
这道题一开始我用dfs写了,但是最后一个数据点没过
然后木有办法就只能再学一次状态压缩,写出来了

思路在代码里:

#include
#define inf 99999999
using namespace std;
double dp[1<<15][20]; //dp数组,第一项表示每个状态,第二项该状态最后一步是哪个位置 
double dis[20][20];	//记录两点之间的距离,邻接矩阵 
int n;

struct point{
	double x, y;
}p[30];

void init(){	//初始化函数 
	cin>>n;
	p[0].x = 0.00, p[0].y = 0.00;
	
	memset(dp, 127, sizeof(dp));	//将dp数组初始化为最大值 
	
	for(int i=1; i<=n; i++){	//输入每个点横纵坐标 
		cin>>p[i].x>>p[i].y;
	}	

	for(int i=0; i<=n; i++){	//计算每两点间的距离 
		for(int j=i+1; j<=n; j++){
			double w = sqrt((p[i].x-p[j].x)*(p[i].x-p[j].x)+(p[i].y-p[j].y)*(p[i].y-p[j].y));
			dis[i][j] = dis[j][i] = w;
		}	
	}	
	
	for(int i=0; i<n; i++){	//用(0,0)到其余各点的距离初始化dp数组 
		dp[1<<i][i] = dis[0][i+1];
	}
}

void dpFuc(){
	for(int i=1; i<(1<<n)-1; i++){	//	每种状态
		for(int pre=0; pre<n; pre++){	//前一位置
		 	if(!(i&(1<<pre)))	//跳过还没走过的位置 
		 		continue;
		 		
		 	for(int now=0; now<n; now++){	//当前位置 
		 		if((i&(1<<now)))	//跳过已经走过的位置 
		 			continue;
				
				//dp数组值取新状态 和 原状态加两点间距离 中最小的一个 
		 		dp[i|(1<<now)][now] = min(dp[i|(1<<now)][now], dp[i][pre] + dis[now+1][pre+1]);
			 }
		 }
	} 	
}

void print(){	//找出最小值并打印 
	double ans = inf;  
	for(int i=0; i<n; i++){
		ans = min(ans, dp[(1<<n)-1][i]);
	}
	printf("%.2f", ans);
}

int main(){
	init();
	dpFuc(); 
	print();
} 

你可能感兴趣的:(动态规划dp)