题目大意:给出n个点,确定一条 连接各点的最短闭合旅程的问题。
解题思路:dp[i][j]表示说从i联通到1,再从1联通到j的距离。
dp[i][j] = dp[i-1][j] + dis(i,i-1);
dp[i][i-1] = min (dp[i][i-1], dp[i-1][j] + dis(i, j));
记忆化代码:
//0 KB 58 ms #include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #include<cmath> using namespace std; int n; double dis[1010][1010]; pair<double,double>point[1010]; double dp[1010][1010]; double dist(int x,int y) { return sqrt((point[x].first-point[y].first)*(point[x].first-point[y].first)+(point[x].second-point[y].second)*(point[x].second-point[y].second)); } double getdp(int x,int y) { double &ans=dp[x][y]; if(ans>=0) return ans; if(x==n-1){ ans=dis[n-1][n]+dis[y][n]; return ans; } ans=min(getdp(x+1,y)+dis[x][x+1],getdp(x+1,x)+dis[y][x+1]); return ans; } int main() { while(~scanf("%d",&n)){ for(int i=1;i<=n;i++){ scanf("%lf%lf",&point[i].first,&point[i].second); // printf("%f %f",point[i].first,point[i].second); for(int j=1;j<=i-1;j++){ dis[i][j]=dis[j][i]=dist(i,j); } } memset(dp,-1,sizeof(dp)); printf("%.2f\n",getdp(1,1)); } return 0; }
//0 KB 12 ms #include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #include<cmath> using namespace std; int n; double dis[1010][1010]; pair<double,double>point[1010]; double dp[1010][1010]; double dist(int x,int y) { return sqrt((point[x].first-point[y].first)*(point[x].first-point[y].first)+(point[x].second-point[y].second)*(point[x].second-point[y].second)); } int main() { while(~scanf("%d",&n)){ for(int i=1;i<=n;i++){ scanf("%lf%lf",&point[i].first,&point[i].second); for(int j=1;j<=i-1;j++){ dis[i][j]=dis[j][i]=dist(i,j); } } for(int i=1;i<n-1;i++) dp[n-1][i]=dis[n-1][n]+dis[i][n]; for(int i=n-2;i>=1;i--) for(int j=1;j<=i;j++){ if(j==i&&i!=1) break; dp[i][j]=min(dp[i+1][j]+dis[i][i+1],dp[i+1][i]+dis[j][i+1]); } printf("%.2f\n",dp[1][1]); } return 0; }