5 6 3 4 1 2 8 6 6 1 8 2 7 4 5 9 3 9 9 5 8 4 1 3 2 6 3 7 2 8 6 4 5 6 3 4 1 2 8 6 6 1 8 2 7 4 5 9 3 9 9 5 8 4 1 3 2 6 3 7 2 1 2 3 2 2 9 10 9 10Sample Output
1 2 3 4 4 5 16 1 2 1 5 4 5 11 1 1 19
题意:
给你一个nXm的格子,要求你从最左走到最右(不限制在某一点=^=,我天,真是蠢到家了,看别人代码才懂这一点)。要求你输出权值最小的路线(格子内的数字为本格的值,每一步所在的行),如果恰好有多条,则按字典序输出路线(比如某条权值相同路线某一点在第3行,两条路线分别走的第2,4行,这时选较小的第2行。)
每一格的走法如图所示:
注意:第一行和最后一行是相连的,类似圆柱。。。
漏点:看了别人代码倒着开始的,但是还不理解为啥,因为懒得想了。。。。等我精力过剩再。。。
贴代码。
#include
#include
#include
using namespace std;
int n,m;
int mp[20][110],dp[20][110],book[20][110];
int main()
{
while(~scanf("%d%d",&n,&m))
{
memset(dp,0,sizeof(dp));
memset(book,0,sizeof(book));
int i,j;
for(i=1; i<=n; i++)
for(j=1; j<=m; j++)
scanf("%d",&mp[i][j]);
//从最右列开始
for(j=m; j>0; j--) //列(这里为我自己加个愚蠢的注释嘤嘤嘤看最下)
for(i=1; i<=n; i++) //行
{
if(j==m)
{
dp[i][j]=mp[i][j];
book[i][j]=i;
}
else
{
//因为权值相同时行按字典序排列,所以有些>=,有些>。
dp[i][j]=dp[i][j+1];
book[i][j]=i;
if(i==n)
{
if(dp[i][j]>=dp[1][j+1])
{
dp[i][j]=dp[1][j+1];
book[i][j]=1;
}
if(dp[i][j]>=dp[i-1][j+1])
{
dp[i][j]=dp[i-1][j+1];
book[i][j]=i-1;
}
}
else if(i==1)
{
if(dp[i][j]>dp[n][j+1])
{
dp[i][j]=dp[n][j+1];
book[i][j]=n;
}
if(dp[i][j]>dp[i+1][j+1])
{
dp[i][j]=dp[i+1][j+1];
book[i][j]=i+1;
}
}
else
{
if(dp[i][j]>=dp[i-1][j+1])
{
dp[i][j]=dp[i-1][j+1];
book[i][j]=i-1;
}
if(dp[i][j]>dp[i+1][j+1])
{
dp[i][j]=dp[i+1][j+1];
book[i][j]=i+1;
}
}
dp[i][j]+=mp[i][j];
}
}
int ans=dp[1][1],f=1;
for(i=1; i<=n; i++)
if(dp[i][1]
最右一列开始,发叉生长,让前面的每一列都能找到根源并有值。