一个求最短路的题目,算不上是TSP吧,只是普通的dp,不过要打印字典序最小的路径,一开始是由后向前递推,结果悲剧了。。。原来打印字典序最小要从前向后递推的,结果后面还是WA了,然后人品爆发,发现一开始打印路径的起始条件为最小权和,终止条件是print_path(int row,int col,int sum)中的sum==0,但其实在中途就有可能会sum==0的,因为节点可以是负数,改成col==n-1就AC了,嘿嘿
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
using namespace std;
long g[12][102],d[12][102];
const long inf=1<<30;
int m,n;
void print_path(int row,int col,long sum)
{
printf("%d",row+1);
sum-=g[row][col];
if(col==n-1) return;
printf(" ");
if(row==0)
{
if(d[row][col+1]==sum)//向右走
{
print_path(row,col+1,sum);
return;
}
if(d[row+1][col+1]==sum)//向右下方走
{
print_path(row+1,col+1,sum);
return;
}
print_path(m-1,col+1,sum);//循环转到第m-1行
return;
}
if(row==m-1)
{
if(d[0][col+1]==sum)//循环转到第0行
{
print_path(0,col+1,sum);
return;
}
if(d[row-1][col+1]==sum)//向右上方走
{
print_path(row-1,col+1,sum);
return;
}
print_path(row,col+1,sum);//向右走
return;
}
if(d[row-1][col+1]==sum)//向右上方走
{
print_path(row-1,col+1,sum);
return;
}
if(d[row][col+1]==sum)//向右走
{
print_path(row,col+1,sum);
return;
}
print_path(row+1,col+1,sum);
}
int main()
{
//以下注释为生成随机数测试样例代码,可无视
/* freopen("in.txt","w",stdout);
// srand((unsigned)time(NULL));
// int t=rand()%10+1;
// printf("%d\n",t);
// while(t--)
// {
// m=rand()%10+1,n=rand()%100+1;
// printf("%d %d\n",m,n);
// for(int i=0;i<m;i++)
// {
// for(int j=0;j<n;j++)
// {
// if(rand()%2)
// {
// g[i][j]=rand();
// }
// else
// {
// g[i][j]=-rand();
// }
// printf("%ld ",g[i][j]);
// }
// printf("\n");
// }
// }
// return 0;
*/
//freopen("in.txt","r",stdin);
//freopen("myout.txt","w",stdout);
while(scanf("%d%d",&m,&n)!=EOF)
{
memset(g,0,sizeof(g));
for(int i=0;i<m;i++)
for(int j=0;j<n;j++)
scanf("%ld",&g[i][j]);
for(int j=0;j<m;j++)
{
for(int k=0;k<n;k++)
{
d[j][k]=inf;
}
}
for(int k=0;k<m;k++)
d[k][n-1]=g[k][n-1];
for(int j=n-2;j>=0;j--)
for(int k=0;k<m;k++)
{
long temp=d[(k-1+m)%m][j+1]+g[k][j];//去右上方
if(temp<d[k][j])//站在k行,j列,到第n-1列的和最小值
{
d[k][j]=temp;
}
temp=d[k][j+1]+g[k][j];//去右边
if(temp<d[k][j])
{
// d[j][k]=min(d[j][k],d[j-1][k]+g[k][j]);
d[k][j]=temp;
}
temp=d[(k+1)%m][j+1]+g[k][j];//去右下方
if(temp<d[k][j])
{
// d[j][k]=min(d[j][k],d[j-1][(k+1)%m]+g[k][j]);
d[k][j]=temp;
}
}
long minnum=inf;
int row;
for(int k=0;k<m;k++)
{
if(d[k][0]<minnum)
{
row=k;
minnum=d[k][0];
}
//printf("%ld ",d[n-1][k]);
}
print_path(row,0,minnum);
printf("\n%ld\n",minnum);
}
return 0;
}