数塔的变形题,样例能过,交上去显示答案错误,求帮忙看一下错在哪里?
题意:给一个m*n的矩阵,让你用一条线 从第1行连到第m行(每行只能选一个元素),要求这条线所经过的元素之和最小。(0<m,n<=100)有以下规定——
1,若你选择了位置(i,j)的元素,那么下一行的元素你只能选择(i+1,j-1)、(i+1,j)、(i+1,j+1)三个之一(当然边界只能选两个)。
2,若可以找到多条 路径上元素之和最小 的线,那么你要优先选择最右边的线。
3,最后从第一行开始 输出线上元素的纵坐标。
我的代码:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int a[105][105],s[105][105],d[105];
int min_index(int mat[],int n){ //在一维数组中找到元素最小值的下标的函数
int i=2,m=1;
if(n==1) return 1;
while(mat[i]<=mat[m] && i<=n){
m=i;
i++;
}
return m;
}
int main(void){
int T,m,n,i,j,k=1,index;
scanf("%d",&T);
while(T--){ //多组数据输入
scanf("%d %d",&m,&n); //数组行数m,列数n
for(i=1;i<=m;i++){
for(j=1;j<=n;j++){
scanf("%d",&a[i][j]);
}
}
memset(s,0,sizeof(s));
printf("Case %d\n",k++);
if(m==1){ //特殊情况讨论:只有一行元素
printf("%d\n",min_index(a[1],n));
continue;
}
else if(n==1){ //特殊情况讨论:只有一列元素
for(i=1;i<=m;i++) printf("1%c",i!=m?' ':'\n');
continue;
}
else{ //一般情况
for(i=2;i<=m;i++){
for(j=2;j<n;j++){
if(a[i-1][j+1]<=a[i-1][j] && a[i-1][j+1]<=a[i-1][j-1]){ //纵坐标不是最头或最尾,有上一行的三个数可以选择
a[i][j]+=a[i-1][j+1]; //先计算最靠右的值是不是最小的
s[i][j]=j+1; //s数组用来存上一行所取元素的列数下标
}
else if(a[i-1][j]<=a[i-1][j+1] && a[i-1][j]<=a[i-1][j-1]){ //最靠右的值如果不是最小,看中间的值是不是最小
a[i][j]+=a[i-1][j];
s[i][j]=j;
}
else{ //最左边的值最小,只能取最左边的值
a[i][j]+=a[i-1][j-1];
s[i][j]=j-1;
}
}
if(a[i-1][2]<=a[i-1][1]){ //对每列第一个元素讨论,只可能取两个值(上一行中间或右边)
a[i][1]+=a[i-1][2];
s[i][1]=2;
}
else{
a[i][1]+=a[i-1][1];
s[i][1]=1;
}
if(a[i-1][n]<=a[i-1][n-1]){ //对每列最后一个元素讨论,只可能取两个值(上一行中间或左边)
a[i][n]+=a[i-1][n];
s[i][n]=n;
}
else{
a[i][n]+=a[i-1][n-1];
s[i][n]=n-1;
}
}
index=min_index(a[m],n);
for(i=m;i>=1;i--){
d[i]=index; //把所有所选元素的列数下标存到数组d中
index=s[i][index];
}
for(i=1;i<=m;i++)
printf("%d%c",d[i],(i!=m)?' ':'\n'); //从第一行开始,输出所选元素的列数下标
}
}
return 0;
}