uva1347 经典dp

来源:互联网 发布:php 中get多个值 编辑:程序博客网 时间:2024/05/14 03:20

     详细的思路书上面有,有一点要强调的是题意容易理解错:必须严格向右或则向左移动,不能到了第3个点又回到第2个点。否则这个状态方程是不成立的,变成了NP难问题

    状态方程:

         dp[i][j]=min(dp[i+1][j]+dis(pos[i],pos[i+1]),dp[i+1][i]+dis(pos[j],pos[i+1]))
由于当前状态取决于i+1状态所以必须逆序。

可以使用滚动数组优化。

AC代码

#include<cstdio>#include<algorithm>#include<cmath>using namespace std;const int maxn=1000;struct node{    double x,y;};node pos[maxn];int n;double dp[2][maxn];inline double dis(const node &a,const node &b){    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}int main(){    while(scanf("%d",&n)==1){        for(int i=1;i<=n;++i)            scanf("%lf%lf",&pos[i].x,&pos[i].y);        //初始化边界        for(int i=1;i<n-1;++i)            dp[0][i]=dis(pos[n],pos[n-1])+dis(pos[n],pos[i]);        int pre=0,now=1;        for(int i=n-2;i>0;--i){            for(int j=i-1;j>0;--j){                dp[now][j]=min(dp[pre][j]+dis(pos[i],pos[i+1]),dp[pre][i]+dis(pos[j],pos[i+1]));            }            pre=(pre+1)%2;            now=(now+1)%2;        }        printf("%.2lf\n",dp[now][1]+dis(pos[1],pos[2]));    }    return 0;}

如有不当之处欢迎指出!

0 0
原创粉丝点击