您的位置:首页 > 其它

动态规划--多阶段决策之单向TSP问题

2018-01-23 17:02 330 查看
多段图是一种特殊的DAG,其节点可以划分成若干个阶段,每个阶段只由上一个阶段所决定。

问题描述

给定一个m行n列(m<=10,n<=100)的整数矩阵,从第一列任何一个位置出发每次往右、右上或者右下走一格,最终到达最后一列。要求经过的整数之和最小。整个矩形是环形的,即第一行的上一行是最后一行,最后一行的下一行是上一行。输出路径上每列的行号,多解时输出字典序最小的那条路径。图1是两个矩阵对应的最后路线(唯一的区别是最后一行)。





图1 矩阵对应的最优路线

分析

在这个题目中,每一列就是一个阶段,每个阶段都有3种决策:直行、右上和右下。
有了前面的经验,不难设计出状态:设d(i,j)为从格子(i,j)出发到最后一列的开销。但是本题不仅要输出解,还要求字典序最小,这就需要计算d(i,j)的同时记录“下一列的行号”的最小值(当然是在满足最优性的前提下)。

代码

int ans=INF,first=0;
for(int j=n-1;j>=0;j++){
for(int i=0;i<m;i++){//逆推
if(j==n-1) d[i][j]=a[i][j] //边界
else{
int row[3]={i,i-1,i+1};
if(i==0) row[1]=m-1;
if(i==m-1) row[2]=0;
/*
chenyuanzheshizhu
sort升序排序,对于数组A中的0~n-1元素进行升序排序,只要写sort(A,A+n)即可
*/
sort(row,row+3);  //这一步的作用是保证字典序最小
d[i][j]=INF;
/*
依次逆序求出每一列的d的最小值,直达第一列,得出第一列最小值及其路径
*/
for(int k=0;k<3;k++){
int v=d[row[k][j+1]]+a[i][j];
if(v<d[i][j]) {d[i][j]=v;next[i][j]=row[k];}
}
}
if(j==0&&d[i][j]<ans){ans=d[i][j];first=i}
}
}
//按照最小字典序打印
printf("%d",first+1);  //输出第一列
for(int i=next[first][0],j=1;j<n;i=next[i][j],j++)
printf(" %d",i+1); //输出其他列
printf("\n%d\n",ans);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息