原題地址(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;
}