现在的位置: 首页 > 综合 > 正文

ZOJ2581

2019年08月20日 ⁄ 综合 ⁄ 共 900字 ⁄ 字号 评论关闭
感觉很强的双调dp问题,不会做,看了解题报告才写的,感觉这题做法比较不错
说的是你从左边一个点走到右边一个点再走回来,要把途中的n-2个点走完,问最短路。
做法是假想两个人从左往右走,一起走到右边那个点的总路径,为了方便,不妨设前面那个人走到i,后一个
走到了j,用dp[i][j]表示这种状态的最短路,然后自底而上刷表,如果下一步是前一个走到i+1,更新就是dp[i+1][j]=min(dp[i+1][j],dp[i][j]+dis(i,i+1)),是后一个就是dp[i+1][i]=min(dp[i+1][i],dp[i][j]+dis(j,i+1)),然后就乱搞就行了。
#include<cstdio>
#include<cmath>
const double INF=9999999;
int n;
int x[101];
int y[101];
double dp[101][101];
double dis(int i,int j)
{
    return sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
}
double min(double a,double b)
{
       return a<b?a:b;
} 
int main()
{
    while(1==scanf("%d",&n))
    {
                            for(int i=1;i<=n;i++)
                                    scanf("%d%d",&x[i],&y[i]);
                            for(int i=1;i<=n;i++)
                            for(int j=1;j<=n;j++)
                               dp[i][j]=INF;
                            dp[1][1]=0;
                            for(int i=1;i<=n;i++)
                            for(int j=1;j<=i;j++)
                            {
                                  dp[i+1][j]=min(dp[i+1][j],dp[i][j]+dis(i,i+1));
                                  dp[i+1][i]=min(dp[i+1][i],dp[i][j]+dis(j,i+1));
                            }
                            double ans=INF;
                            for(int j=1;j<n;j++)
                            if(ans>dp[n][j]+dis(j,n))
                              ans=dp[n][j]+dis(j,n);
                             printf("%.2f\n",ans);  
                            
    }
    return 0;
} 

【上篇】
【下篇】

抱歉!评论已关闭.