池塘里有n片荷叶,围成了一个凸多边形。荷叶的编号分别为1,2,3,。。n,n<=1000, 求一种青蛙的跳跃策略,使得青蛙跳过的距离最短,并且遍历了所有的荷叶
分析:最短距离并非遍历凸多边形的所有的边。例如:A(2 3),B(6 3),C(4 1),D(1 1),四个点组成的凸多边形,最短的遍历路径为ADBC,经过了对角线DB。
使用动态规划解这道题目。子问题为每个节点周围节点数目为1,2,3,..,时候的问题,在解题的过程中,不断的扩大每个节点周围的节点数目。
f(s,L,0)表示从s开始,经过L个顶点的最短距离
f(s,L,1)表示从s+L-1开始,经过L个顶点的最短距离
则 f(s,L,0)=min(f(s+1,L-1,0)+dis(s,s+1), f(s+1,L-1,1)+dis(s,s+L-1));
f(s,L,1)=min(f(s,L-1,1)+dis(s+L-1,s+L-2), f(s,L-1,0)+dis(s,s+L-1));
f[s,1,0]=0;
f[s,1,1]=0;
#ifndef FROGSTROUBLE_H #define FROGSTROUBLE_H class FrogsTrouble { int n; double *x,*y; double **dist; double ***f; double ans; public: FrogsTrouble(); double getResult(); int min(int x,int y); }; #endif
#include “stdafx.h” #include “FrogsTrouble.h” #include <iostream> #include “math.h” using namespace std; FrogsTrouble::FrogsTrouble() { cin>>n; this->x=new double[n]; this->y=new double[n]; this->dist=new double*[n]; this->f=new double**[n]; for(int i=0;i<n;i++) { dist[i]=new double[n]; f[i]=new double*[2]; for(int j=0;j<=n;j++) { f[i][j]=new double[2]; } } for(int i=0;i<n;i++) { cin>>x[i]>>y[i]; } for(int i=0;i<n-1;i++) { for(int j=i+1;j<n;j++) { dist[i][j]=sqrt((x[j]-x[i])*(x[j]-x[i])+(y[j]-y[i])*(y[j]-y[i])); dist[j][i]=dist[i][j]; } } int sign=0; this->ans=100000.0; for(int j=1;j<=n;j++) { sign=1-sign; for(int i=n-1;i>=0;i–) { if(j==1) { f[i][sign][0]=0; f[i][sign][1]=0; } else { f[i][sign][0]=min(f[(i+1)%n][1-sign][0]+dist[i][(i+1)%n],f[(i+1)%n][1-sign][1]+dist[i][(i+j-1)%n]); f[i][sign][1]=min(f[i][1-sign][0]+dist[(i+j-1)%n][i],f[(i)%n][1-sign][1]+dist[(i+j-1)%n][(i+j-2)%n]); if(j==n) { ans=min(ans,f[i][sign][0]); } } } } } double FrogsTrouble::getResult() { //cout<<ans<<endl; return ans; } int FrogsTrouble::min(int x, int y) { return x<y?x:y; }