这道题呢,原型就应该是数塔,是一个比较基础的动态规划 + 回溯路径,还有一点,这个题意,我最开始竟然没有读懂,实际就是找到一条权值和从上到下最短的。
#include<iostream>
#include<cstdio>#include<string.h>
#include<string>
#include<stack>
#include<set>
#include<algorithm>
#include<cmath>
#include<vector>
#include<map>
#include<sstream>
#include<queue>
#define ll __int64
#define lll unsigned long long
#define MAX 1000009
#define MAXN 2009
#define eps 1e-8
#define INF 0x7fffffff
#define mod 1000000007
#define clr(a) memset(a,0,sizeof(a))
#define clr1(a) memset(a,-1,sizeof(a))
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
using namespace std;
inline ll Max(ll a,ll b)
{
return a>b?a:b;
}
inline ll Min(ll a,ll b)
{
return a<b?a:b;
}
int dp[109][109];
int a[109][109];
int path[109][109];
int ans[109];
void print(int num,int index)
{
if(num<1)return ;
if(path[num][index]==-1)
{
printf("%d",index);
return ;
}
else
{
print(num-1,path[num][index]);
printf(" %d",index);
}
}
int main()
{
#ifdef ONLINE_JUDGE
#else
freopen("ans.txt","r", stdin);
//freopen("out.txt","r", stdout);
#endif
int T;
int d = 1;
int m,n;
scanf("%d",&T);
while(T--)
{
clr(a);
clr1(path);
scanf("%d%d",&n,&m);
for(int i = 0; i<109; i++)
for(int j = 0; j<109; j++)
dp[i][j] = MAX;
for(int i = 1; i<=n; i++)
for(int j = 1; j<=m; j++)
scanf("%d",&a[i][j]);
for(int i = 1; i<=m; i++) dp[1][i] = a[1][i];
for(int i = 2; i<=n; i++)
{
for(int j = 1; j<=m; j++)
{
if(j!=1&&dp[i][j] > dp[i - 1][j - 1] + a[i][j])
{
dp[i][j] = dp[i - 1][j - 1] + a[i][j];
path[i][j] = j - 1;
}
if(dp[i][j] >= dp[i - 1][j] + a[i][j])
{
dp[i][j] = dp[i - 1][j] + a[i][j];
path[i][j] = j;
}
if(j!=m&&dp[i][j] >= dp[i - 1][j + 1] + a[i][j])
{
dp[i][j] = dp[i - 1][j + 1] + a[i][j];
path[i][j] = j + 1;
}
}
}
int index = -1;
int _min = INF;
for(int i = m; i>=1; i--)
{
if(_min > dp[n][i])
{
_min = dp[n][i];
index = i;
}
}
printf("Case %d\n",d++);
print(n,index);
puts("");
}
return 0;
}