/*SE:wn------王宁*/
这是一道简单的多阶段决策题目,但是要注意细节处理。
#include<bits/stdc++.h>
using namespace std;
const int maxr=15;
const int maxc=105;
int mat[maxr][maxc];
int d[maxr][maxc];
int path[maxc];
int main()
{
int m,n,i,j,ans,p,t;
while(~scanf("%d%d",&m,&n))
{
for(i=0;i<m;i++)
for(j=0;j<n;j++) scanf("%d",&mat[i][j]);
/*我也是用逆推的,不过并没有用next记录下一个位置
而是采用相邻位置dp值的差值是否等于前一个元素
并用临时变量来确定最小字典序*/
for(j=m-1;j>=0;j--) d[j][n-1]=mat[j][n-1];
for(i=n-2;i>=0;i--)
for(j=0;j<m;j++)
{
d[j][i]=min(mat[j][i]+d[j][i+1],mat[j][i]+d[(j-1+m)%m][i+1]);
d[j][i]=min(d[j][i],mat[j][i]+d[(j+1+m)%m][i+1]);
}
ans=d[0][0],p=0;
for(i=1;i<m;i++) if(d[i][0]<ans){ ans=d[i][0]; p=i; }
for(i=0;i<m;i++) if(d[i][0]==ans) { p=i; break; }
printf("%d",p+1);
for(i=1;i<n;i++)
{
/*t一开始如果没有赋值,初值是0,而如果没有正确的在第一次比较中
就将t改变过来,那么后面即使找到对的路径也不能比t(t=0)小了,
之后就会出现连续的错误
所以为了每次使用都能到达既能走通,又是字典序最小的状况
t作为记录位置的参数应该设置的很大——肯定有值能将它改变但是也要让人家
达到你的门槛*/
t=10000000;
if(d[(p-1+m)%m][i]==d[p][i-1]-mat[p][i-1]) { t=(p-1+m)%m; }
if((d[(p)%m][i]==d[p][i-1]-mat[p][i-1])&&p<t) { t=p; }
if((d[(p+1+m)%m][i]==d[p][i-1]-mat[p][i-1])&&(p+1+m)%m<t) { t=(p+1+m)%m; }
p=t;
printf(" %d",t+1);
}
printf("\n%d\n",ans);
}
return 0;
}