欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

P1433 吃奶酪 题解 状态压缩 DP

程序员文章站 2024-03-23 23:03:22
...

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

思路在代码里:

#include<bits/stdc++.h>
#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();
} 
相关标签: 状态压缩