您的位置:首页 > 其它

hdu 2224 The shortest path 题解(动态规划)

2014-06-28 21:22 393 查看
点击打开链接

The shortest path

Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 746 Accepted Submission(s): 383



[align=left]Problem Description[/align]
There are n points on the plane, Pi(xi, yi)(1 <= i <= n), and xi < xj (i<j). You begin at P1 and visit all points then back to P1. But there is a constraint:

Before you reach the rightmost point Pn, you can only visit the points those have the bigger x-coordinate value. For example, you are at Pi now, then you can only visit Pj(j > i). When you reach Pn, the rule is changed, from now on you can only visit the points
those have the smaller x-coordinate value than the point you are in now, for example, you are at Pi now, then you can only visit Pj(j < i). And in the end you back to P1 and the tour is over.

You should visit all points in this tour and you can visit every point only once.

[align=left]Input[/align]
The input consists of multiple test cases. Each case begins with a line containing a positive integer n(2 <= n <= 200), means the number of points. Then following n lines each containing two positive integers Pi(xi, yi), indicating
the coordinate of the i-th point in the plane.

[align=left]Output[/align]
For each test case, output one line containing the shortest path to visit all the points with the rule mentioned above.The answer should accurate up to 2 decimal places.

[align=left]Sample Input[/align]

3
1 1
2 3
3 1


[align=left]Sample Output[/align]

6.47

Hint: The way 1 - 3 - 2 - 1 makes the shortest path.题意:给N个二维平面上面的点,要从第一个点走到第N个点(若从i到j,必须i<j),再从第N个点走回第一个点(若从i到j,必须i>j),每个点只能访问且必须访问一次,求最短路径。我们把从第一个点到第N个点的路径看成路径0,第N个点到第一个点的路径看成路径1,那么除开第一个点和第N个点,其余每个点只有两种策略,要么在路径0,要么在路径1。我们从第N个点开始选,依次选点N-1,N-2.....1,这样定义状态 dp[i][x][y],表示n到i已经选过,路径0以x结束,路径1以y结束的最短路径(除开第N个点其余点只能在一条路径上),显然x和y其中一个一定是i,所以可以将空间优化到两维,dp[i][0][j]表示i在路径0,路径1以j结束的最短路径,dp[i][1][j]则表示i在路径1,路径0以i结束的最短路径。很容易写出转移方程:dp[i][0][j]=max(dp[i][0][j],dp[i+1][0][j]+dis(i+1,i)),i+1<=j<=n;dp[i][0][i+1]=max(dp[i][0][i+1],dp[i+1][1][j]+dis(i,j)),i+1<=j<=n;同理可得dp[i][1][j],dp[i][1][j+1]的转移方程,具体代码如下:[code]#include<stdio.h>
#include<iostream>
#include<string>
#include<string.h>
#include<vector>
#include<algorithm>
#include<queue>
#include<stack>
#include<math.h>
#define nn 110
#define inff 0x3fffffff
#define mod 1000000007
#define eps 1e-9
using namespace std;
typedef long long LL;
struct node
{
int x,y;
}a[2*nn];
int n;
double dp[2*nn][2][2*nn];
double dis(int i,int j)
{
double f1=(a[i].x-a[j].x)*(a[i].x-a[j].x)+(a[i].y-a[j].y)*(a[i].y-a[j].y);
return sqrt(f1);
}
int main()
{
int i,j,k;
while(scanf("%d",&n)!=EOF)
{
for(i=1;i<=n;i++)
{
scanf("%d%d",&a[i].x,&a[i].y);
}
for(i=1;i<=n;i++)
{
for(j=0;j<=1;j++)
{
for(k=1;k<=n;k++)
{
dp[i][j][k]=1e20;
}
}
}
dp
[0]
=0;
dp
[1]
=0;
for(i=n-1;i>=0;i--)
{
for(j=i+1;j<=n;j++)
{
dp[i][0][j]=min(dp[i][0][j],dp[i+1][0][j]+dis(i,i+1));
dp[i][1][j]=min(dp[i][1][j],dp[i+1][1][j]+dis(i,i+1));
}
for(j=i+1;j<=n;j++)
{
dp[i][0][i+1]=min(dp[i][0][i+1],dp[i+1][1][j]+dis(i,j));
dp[i][1][i+1]=min(dp[i][1][i+1],dp[i+1][0][j]+dis(i,j));
}
}
double ans=1e20;
for(i=1;i<=n;i++)
{
ans=min(ans,dp[1][0][i]+dis(1,i));
ans=min(ans,dp[1][1][i]+dis(1,i));
}
printf("%.2lf\n",ans);
}
return 0;
}


[/code]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: