1. 程式人生 > 其它 >2022春每日一題:Day 19

2022春每日一題:Day 19

題目:吃乳酪

狀壓dp實現,dp[i][j]表示走過狀態i,停到了j的位置的最小价值。列舉狀態,起點終點,轉移dp[i][j]=min{dp[i-(1<<s)][k]+dis(s,k)} 其中(s!=k,dis(s,k)表示s和k的歐幾里得距離)。
時間複雜度O(n2*2n),跑的還算快。

程式碼:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
int n;
double x[16],y[16],dp[1<<16][16];
double get(int a,int b)
{
	return sqrt((x[a]-x[b])*(x[a]-x[b])+(y[a]-y[b])*(y[a]-y[b]));
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	    scanf("%lf %lf",&x[i],&y[i]);
	++n;
	for(int i=0;i<(1<<n);i++)
	    for(int j=0;j<n;j++)
	        dp[i][j]=1e5;
	dp[1][0]=0;
	for(int i=0;i<(1<<n);i++)
		for(int j=0;j<n;j++)
		    if(i>>j&1)
		        for(int k=0;k<n;k++)
		            if((i-(1<<j)>>k)&1)
		                dp[i][j]=min(dp[i][j],dp[i-(1<<j)][k]+get(j,k));
	double ret=1e4;
	for(int i=0;i<n;i++)
	    ret=min(ret,dp[(1<<n)-1][i]);
	printf("%.2lf\n",ret);
	return 0;
}