题意:给一个矩阵,每个元素是一个整数,求从上到下的“一条线”,使得这些数的和最小。
思路:简单dp。记录从最上面到当前元素的最优解。
#include<stdio.h>
#include<iostream>
#include<memory.h>
#include<vector>
using namespace std;
#define ll long long
#define INF 1000000000000000LL
int mp[110][110];
ll dp[110][110];
int path[110][110];
int main(){
int t;
cin>>t;
int cas=0;
while(t--){
cas++;
int m,n;
cin>>m>>n;
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++){
scanf("%d",&mp[i][j]);
}
}
for(int i=1;i<=n;i++){
dp[0][i]=0;
}
for(int i=0;i<=m+1;i++){
dp[i][0]=dp[i][n+1]=INF;
}
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++){
int x;
if(dp[i-1][j-1]<dp[i-1][j]){
if( dp[i-1][j-1]<dp[i-1][j+1] ){
x=j-1;
}else{
x=j+1;
}
}else{
if( dp[i-1][j]<dp[i-1][j+1] ){
x=j;
}else{
x=j+1;
}
}
dp[i][j]=dp[i-1][x]+mp[i][j];
path[i][j]=x;
}
}
int k=1;
ll ans=dp[m][1];
for(int i=2;i<=n;i++){
if(dp[m][i]<=ans){
ans=dp[m][i];
k=i;
}
}
printf("Case %d\n",cas);
vector<int> v;
for(int i=m;i>=1;i--){
v.push_back(k);
k=path[i][k];
}
for(int i=m-1;i>=0;i--){
printf("%d",v[i]);
if(i)printf(" ");
}
cout<<endl;
}
return 0;
}