题目地址:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=52
这是一道比较简单的DP
题意就是在一个n*m的矩阵,每一(i,j)都有一个值
从第1列到第m列,要你找一条路径出来
使得相加的和最少
可以往后一列的行-1,当前行,行+1
如果是在边界行,则可以循环,题目中说的比较清楚
这一看就是很明显的DP,但是有一个问题
输出路径的时候如果有多条路径,输出字典序最小的那个
如果从前往后递推的话,那么最后保存答案的时候就要从后面往前
但是字典序是从第一个开始比较的,所以你不清楚你的到底会不会是最小的字典序
那么我们就把这个倒过来
从后往前递推,保存答案的时候从前往后保存
这样就十分的清除,我们找的就是最小的字典序的路径
下面看我的代码:
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = 110;
int dp[maxn][maxn];
int behind[maxn][maxn];
int n,m;
int ans[maxn];
void read()
{
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
scanf("%d",&dp[i][j]);
}
}
void solve()
{
for(int j=m-2;j>=0;j--)
{
for(int i=0;i<n;i++)
{
int up = i-1;
int mid = i;
int down = (i+1)%n;
if(i==0)
{
up = n-1;
if(dp[mid][j+1]<=dp[up][j+1] && dp[mid][j+1]<=dp[down][j+1])
{
dp[i][j]+=dp[mid][j+1];
behind[i][j] = mid;
}
else if(dp[down][j+1]<=dp[up][j+1] && dp[down][j+1]<=dp[mid][j+1])
{
dp[i][j]+=dp[down][j+1];
behind[i][j] = down;
}
else if(dp[up][j+1]<=dp[down][j+1] && dp[up][j+1]<=dp[mid][j+1])
{
dp[i][j]+=dp[up][j+1];
behind[i][j] = up;
}
}
else if(i==n-1)
{
if(dp[down][j+1]<=dp[up][j+1] && dp[down][j+1]<=dp[mid][j+1])
{
dp[i][j]+=dp[down][j+1];
behind[i][j] = down;
}
else if(dp[up][j+1]<=dp[down][j+1] && dp[up][j+1]<=dp[mid][j+1])
{
dp[i][j]+=dp[up][j+1];
behind[i][j] = up;
}
else if(dp[mid][j+1]<=dp[up][j+1] && dp[mid][j+1]<=dp[down][j+1])
{
dp[i][j]+=dp[mid][j+1];
behind[i][j] = mid;
}
}
else
{
if(dp[up][j+1]<=dp[down][j+1] && dp[up][j+1]<=dp[mid][j+1])
{
dp[i][j]+=dp[up][j+1];
behind[i][j] = up;
}
else if(dp[mid][j+1]<=dp[up][j+1] && dp[mid][j+1]<=dp[down][j+1])
{
dp[i][j]+=dp[mid][j+1];
behind[i][j] = mid;
}
else if(dp[down][j+1]<=dp[up][j+1] && dp[down][j+1]<=dp[mid][j+1])
{
dp[i][j]+=dp[down][j+1];
behind[i][j] = down;
}
}
}
}
int min = 0x3f3f3f;
int min2;
for(int i=0;i<n;i++)
{
if(dp[i][0]<min)
{
min = dp[i][0];
min2 = i;
}
}
ans[0] = min2;
for(int i=1;i<m;i++)
{
ans[i] = behind[ans[i-1]][i-1];
}
for(int i=0;i<m;i++)
{
if(!i)
printf("%d",ans[i]+1);
else
printf(" %d",ans[i]+1);
}
printf("\n%d\n",min);
}
void out()
{
printf("----------------------------------\n");
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
printf("%d ",dp[i][j]);
printf("\n");
}
printf("----------------------------------\n");
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
read();
//out();
solve();
//out();
}
}