zoj 2581

 同时也是 POJ 2677 双调欧几里德旅行商问题
    设dp[i][j] 表示快的人走到i,慢的人走到j时的最小路程 (j<i)
    从左到右对于每个点要么给走的快的人,要么给走的慢的人
    初始化 dp[i][j]=INF  
    状态转移方程:
    f[i+1][i] = min{f[i+1][i], f[i][j]+dis[j][i+1]} 此前为f[i][j],当前点i+1分配给j 
    f[i+1][j] = min{f[i+1][j], f[i][j]+dis[i][i+1]} 此前为f[i][j],当前点i+1分配给i 
    其中 0<=j<i
    最后 结果为 min(f[n][i]+dis(i,n)) 其中 i<n 
View Code
1 #include<iostream>
2 #include<cmath>
3 #include<cstdio>
4 #include<cstring>
5 #define INF 100000000
6 using namespace std;
7 double dp[100][100];
8 double x[100],y[100];
9 double dis(int i,int j)
10 {
11 return sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
12 }
13 double min(double w,double t)
14 {
15 if(w>t)return t;
16 else return w;
17 }
18 int n;
19 int main()
20 {
21 int i,j;
22 while(cin>>n)
23 {
24 for(i=0;i<n;i++)
25 cin>>x[i]>>y[i];
26 memset(dp,0,sizeof(dp));
27 for(i=0;i<n;i++)
28 for(j=0;j<n;j++)
29 dp[i][j]=INF;
30 dp[1][0]=dis(0,1);
31 n--;
32 for(i=0;i<n;i++)
33 for(j=0;j<i;j++)
34 {
35 dp[i+1][i]=min(dp[i+1][i],dp[i][j]+dis(j,i+1));//慢的走第i+1个点
36 dp[i+1][j]=min(dp[i+1][j],dp[i][j]+dis(i,i+1));//快的走第i+1个点
37 }
38 double res=INF;
39 for(i=0;i<n;i++)
40 res=min(res,dp[n][i]+dis(i,n));
41 printf("%.2lf\n",res);
42 }
43 return 0;
44 }
posted @ 2011-07-08 11:44  我们一直在努力  阅读(258)  评论(0编辑  收藏  举报