/* 题不难,不过做的时候状态没有考虑清楚,所以耗时很大。出发和结尾无限制,字典序越小越好。 重点注意:状态是二维的,所以要是做存储结构时,也要注意必须使用二维数组,否则会冲掉一些数据。 题意:旅行商问题,从第一列走到最后一列,耗时最少需要怎么走,走法受限制,第一行和最后一行相邻。 */ //#define TEST #include <cstdio> #include <cstring> const int nMax=107,INF=0x7fffffff;//nMax原来为100结果WA! int map[nMax][nMax]; int d[nMax][nMax]; int ans[nMax][nMax]; int m,n; int dp(int x,int y) { int &temp=d[x][y]; if(temp!=-1) return temp; temp=INF>>1; if(x==m-1 && dp(0,y+1)+map[x][y]<temp) temp=dp(ans[x][y]=0,y+1)+map[x][y]; if(x>0 && dp(x-1,y+1)+map[x][y]<temp) temp=dp(ans[x][y]=x-1,y+1)+map[x][y]; if(dp(x,y+1)+map[x][y]<temp) temp=dp(ans[x][y]=x,y+1)+map[x][y]; if(x<m-1 && dp(x+1,y+1)+map[x][y]<temp) temp=dp(ans[x][y]=x+1,y+1)+map[x][y]; if(x==0 && dp(m-1,y+1)+map[x][y]<temp) temp=dp(ans[x][y]=m-1,y+1)+map[x][y]; #ifdef TEST printf("%d %d %d\n",x,y,ans[y]); #endif return temp; } int main() { //freopen("f://data.in","r",stdin); while(scanf("%d%d",&m,&n)!=EOF) { for(int i=0;i<m;i++) for(int j=0;j<n;j++) scanf("%d",&map[i][j]); int min=INF; int p; memset(d,-1,sizeof(d)); for(int j=0;j<m;j++) d[j][n]=0; for(int i=0;i<m;i++) { if(dp(i,0)<min) { p=i; min=dp(i,0); } } int z=0; while(z<n) { if(z) printf(" "); printf("%d",p+1); p=ans[p][z++]; } printf("\n"); printf("%d\n",min); } return 0; }