洛谷 P1433 吃奶酪 (状压dp)

-
题意:RT,老鼠可以在任意两点移动.
-
分析:由于\(n\)的范围非常小,我们考虑状压,我刚开始是用一维dp转移的,但是这样的话会出现一个问题,也就是我们从上一个状态转移过来时,会出现不同坐标但状态值相同的情况,那么我们用一维就不能确定哪个坐标是最优的,所以要用二维dp来进行转移.\(dp[i][j]\)表示状态为\(j\),并且当前在第\(i\)个坐标的最短距离.那么转移的话,就从上一个状态的每一个点转移过来.
-
代码:
#include <bits/stdc++.h> #define ll long long #define fi first #define se second #define pb push_back #define me memset #define min(a,b) (((a)<(b))?(a):(b)) #define rep(a,b,c) for(int a=b;a<=c;++a) #define per(a,b,c) for(int a=b;a>=c;--a) const int N = 1e6 + 10; const int mod = 1e9 + 7; const int INF = 0x3f3f3f3f; using namespace std; typedef pair<int,int> PII; typedef pair<ll,ll> PLL; ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;} ll lcm(ll a,ll b) {return a/gcd(a,b)*b;} int n; double x[20],y[20]; double dp[20][35000]; double get_dis(double x1,double y1,double x2,double y2){ return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)); } int main(){ ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); cin>>n; rep(i,0,n-1) cin>>x[i]>>y[i]; me(dp,127,sizeof(dp)); rep(i,1,(1<<n)-1){ rep(j,0,n-1){ if((i&(1<<j))==0) continue; if(i==(1<<j)){ dp[j][i]=0; continue; } rep(k,0,n-1){ if(j==k) continue; if((i&(1<<k))==0) continue; double dis=get_dis(x[j],y[j],x[k],y[k]); dp[j][i]=min(dp[j][i],dp[k][i-(1<<j)]+dis); } } } double ans=1e18; rep(i,0,n-1){ ans=min(ans,dp[i][(1<<n)-1]+get_dis(x[i],y[i],0.0,0.0)); } cout<<fixed<<setprecision(2)<<ans<<'\n'; return 0; }
𝓐𝓬𝓱𝓲𝓮𝓿𝓮𝓶𝓮𝓷𝓽 𝓹𝓻𝓸𝓿𝓲𝓭𝓮𝓼 𝓽𝓱𝓮 𝓸𝓷𝓵𝔂 𝓻𝓮𝓪𝓵
𝓹𝓵𝓮𝓪𝓼𝓾𝓻𝓮 𝓲𝓷 𝓵𝓲𝓯𝓮

浙公网安备 33010602011771号