原题地址(vjudge)
这题还是有点意思的,你珂以理解为要找两条除了起点和终点之外没有任何点是相等的路径。这题就和某经典题不太一样了,某经典题是可以重复的。所以用
表示同时走到第
个点和第
个点就不是很好了。那怎么表示呢?珂以用
表示同时走到
和
且
全部都走过。易得
,规定一下所有状态必须
,
状态转移方程:
表示第一个人从
,所以加上
,
原式等于
,即从
(
),只不过要保持第一维小于第二维,所以只能转成
,加上
,初始条件:
for(int i=1;i<=n;i++) dp[n][i]=dis[n][i]; //第一个已经到达n,所以答案为dis[n][i]
路径预处理:
void compare(void)
{
memset(dp,0,sizeof(dp)) ;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
double c=sqrt(abss(x[i]-x[j])*abss(x[i]-x[j])+abss(y[i]-y[j])*abss(y[i]-y[j])); //abss指绝对值
g[i][j]=g[j][i]=c;
}
}
return ;
}
状态转移:
for(int i=n-1;i>=2;i--)
{
for(int j=1;j<i;j++)
{
dp[i][j]=min(dp[i+1][j]+g[i][i+1],dp[i+1][i]+g[i+1][j]);
}
}
:
# include <bits/stdc++.h>
using namespace std;
int n;
const int N=1010;
double x[N],y[N];
double g[N][N];
double dp[N][N];
double abss(double a)
{
if(a>=0) return a;
return -a;
}
void compare(void)
{
memset(dp,0,sizeof(dp)) ;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
double c=sqrt(abss(x[i]-x[j])*abss(x[i]-x[j])+abss(y[i]-y[j])*abss(y[i]-y[j]));
g[i][j]=g[j][i]=c;
}
}
for(int i=1;i<=n;i++) dp[n][i]=g[n][i];
return ;
}
void solve(void)
{
for(int i=n-1;i>=2;i--)
{
for(int j=1;j<i;j++)
{
dp[i][j]=min(dp[i+1][j]+g[i][i+1],dp[i+1][i]+g[i+1][j]);
}
}
cout<<fixed<<setprecision(2)<<dp[2][1]+g[2][1]<<endl ;
}
int main(void)
{
while(~scanf("%d",&n))
{
for(int i=1;i<=n;i++)
{
cin >> x[i] >> y[i];
}
compare() ;
solve() ;
}
return 0;
}