注意只有一列的情况
要求字典序很小就先遍历行号小的,再遍历行号大的
样例试不出来的bug真是令人头禿
按照我代码习惯,我喜欢在开始初始化,导致n=1的情况下,for循环进不去。。。
先看数据先看数据先看数据,先想特例先想边界
这个和数塔也挺像的,肯定要从最后一列往前去累加
#include<stdio.h>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long LL;
const int INF=0x3f3f3f3f;
int mat[15][110];
LL dp[15][110];
int nxt[15][110];
int m,n;
int main()
{
// freopen("in.txt","r",stdin);
while(scanf("%d%d",&m,&n)!=EOF)
{
int ans=INF,first=0;
memset(dp,INF,sizeof(dp));
memset(nxt,0,sizeof(nxt));
for(int i=1;i<=m;++i)
for(int j=1;j<=n;++j)
scanf("%d",&mat[i][j]);
for(int i=1;i<=m;++i)
dp[i][n]=mat[i][n];
if(n==1)
{
for(int i=1;i<=m;++i)
{
if(dp[i][1]<ans)
{
ans=dp[i][1];
first=i;
}
}
}
else //只有一列的时候进不来
{
for(int j=n-1;j>=1;--j) //序
{
for(int i=1;i<=m;++i)
{
//三个比较的思路很好想,取min即可
int row[3]={i-1,i,i+1};
if(i==1) row[0]=m; //把行数写成n了,傻子啊
if(i==m) row[2]=1;
sort(row,row+3); //巧妙
for(int k=0;k<3;++k)
{
int v=dp[row[k]][j+1]+mat[i][j];
if(v<dp[i][j])
{
dp[i][j]=v;
nxt[i][j]=row[k];
}
}
//可以从第一列任意一行开始
if(j==1&&dp[i][j]<ans)
{
ans=dp[i][j];
first=i;
}
}
}
}
printf("%d",first);
for(int i=nxt[first][1],j=2;j<=n;i=nxt[i][j],j++)
printf(" %d",i);
printf("\n%d\n",ans);
}
}