题目地址:点击 UVA 1347 链接
样例输入:
3
1 1
2 3
3 1
4
1 1
2 3
3 1
4 2
样例输出:
6.47
7.89
题意: 给你n个点 你的任务是求出从最左边点到最右边点 再从最右边点 回来的最短路径 (要求没个点都要走一遍) 。。
思路: dp[i][j] 我们假设同时有两个人在走 那么,两个人走的 路径不同 ,但是尽量短的走 ,那么走到两个人都走到第n个点,就会出现一个最短路径。我们假设两个人的当前位置分别是 i 和 j 那么dp[i][j] 看可以转移到 dp[i+1][j] 和 dp[i+1][i] 两种状态。分别表示 i 走到i+1 和 j 走到 i+1 个点。。 (注意 j 走到i+1 本应该转移到dp[i][i+1] 但是 我们 规定 i>j 其实也是为了 更好的去求解。 )
那么初始状态 就是dp[n][i](i>=1&&i<=n) dp[n][i]=dis[n][i];
那么状态转移方程我们也可以很好的推出来 因为dp[i][j] 可以转移到dp[i+1][j] 和dp[i+1][i] 两种状态 ,那么dp[i][j] 的状态当然也是由 dp[i+1][j] he dp[i+1][i] 两种状态倒着退回来 。 dp[i][j]=min(dp[i+1][j]+dis[i+1][i],dp[i+1][i]+dis[j][i+1])
代码:
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<iostream>
#include<algorithm>
#define N 1005
using namespace std;
double dp[N][N];
double dis[N][N];
struct node
{
int x,y;
}a[N];
int n;
double juli(int i,int j)
{
int x,y;
double fin;
x=abs(a[i].x-a[j].x); y=abs(a[i].y-a[j].y);
fin=x*x+y*y;
return sqrt(fin);
}
void memdp()
{
for(int i=1;i<=n;i++) dp[n][i]=dis[n][i];
for(int i=n-1;i>=1;i--)
{
for(int j=1;j<=i;j++)
{
dp[i][j]=min(dp[i+1][j]+dis[i+1][i],dp[i+1][i]+dis[j][i+1]);
}
}
printf("%.2f\n",dp[1][1]);
return ;
}
void chushihua()
{
for(int i=0;i<=n;i++)
{
for(int j=0;j<=n;j++)
{
dp[i][j]=dis[i][j]=0.0;
}
}
return ;
}
int main()
{
while(cin>>n)
{
for(int i=1;i<=n;i++) cin>>a[i].x>>a[i].y;
chushihua();
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
double dist=juli(i,j);
dis[i][j]=dist;
}
}
memdp();
}
return 0;
}