给一个m*n的矩阵 每个格子有一个值 输出一种走到最后一列的走法,使得路过的格子的值的和最小且字典序最小。
设d[i][j]为从(i,j)到最后一列的最小开销,那么最后一列的格子的d值就是格子本身的值。每一次有三种决策:右上、直右和右下,一步步推就行。
为了保存最小字典序,排序是必要的。
AC代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int INF=0x3f3f3f3f;
int a[110][110],Next[110][110],dp[110][110];
int main()
{
int n,m;
while(cin>>m>>n&&m)
{
for(int i=0;i<m;i++)
for(int j=0;j<n;j++)
scanf("%d",&a[i][j]);
int ans=INF,first=0;
for(int j=n-1;j>=0;j--)
{
for(int i=0;i<m;i++)
{
if(j==n-1) dp[i][j]=a[i][j];
else
{
int rows[3]={i,i-1,i+1};
if(i==0) rows[1]=m-1;
if(i==m-1) rows[2]=0;
sort(rows,rows+3);
dp[i][j]=INF;
for(int k=0;k<3;k++)
{
int v=dp[rows[k]][j+1]+a[i][j];
if(v<dp[i][j]) { dp[i][j]=v;Next[i][j]=rows[k]; }
}
}
if(j==0&&dp[i][j]<ans) { ans=dp[i][j];first=i; }
}
}
cout<<first+1;
for(int i=Next[first][0],j=1;j<n;i=Next[i][j],j++)
cout<<' '<<i+1;
cout<<endl<<ans<<endl;
}
return 0;
}