穿越矩陣

hushhw發表於2017-11-04
穿越矩陣

現在有一個 m * n 的整數矩陣,每一格上有一個數字。請你編寫一個程式計算出一條從左到右穿過矩陣的路徑,並使此路徑的費用最小。路徑的花費是指這條路徑所穿越的所有單元格中的數字之和。

路徑從矩陣的左側的第一列的任意單元格開始,逐步穿過矩陣到達最右側的一列的任意單元格。每一步是指從某單元格進入它右側一列的相鄰單元格(如下圖,可以是橫向或斜向)。矩陣的第一行和最後一行實際是相鄰的,你可以想象矩陣是包裹在一個橫放的圓柱體外面。

穿越兩個略有不同的 5 * 6 的矩陣的路徑如下圖所示,這兩個矩陣只有最後一行的數字不同。右側的路徑顯示了第一行和最後一行相鄰的效果。

輸入

輸入包括一系列矩陣描述。每個矩陣描述的第一行是 m 和 n,即矩陣的行數和列數;之後的 m 行,每行包括 n 個以空格分開的整數,則是當前矩陣的值,注意矩陣的值未必是正數。

矩陣的行數 m 和列數 n 的範圍是:1 <= m <= 10、 1 <= n <= 100;所有路徑的費用值都可以用 30bit 的整數表示。

輸出

針對每一個矩陣,找出費用最小的路徑,並將其輸出。每個矩陣的輸出包括兩行,第一行是路徑本身,即輸出每一步所在的行,第二行則是該路徑的費用。

如果對於同一個矩陣有多條不同的費用最小路徑,則輸出左端行號較小的一條。

Sample input

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

Sample Output

1 2 3 4 4 5

16

1 2 1 5 4 5

11


#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
int a[11][101],dp[11][101];
int num[101];

int main()
{
	int m,n;
	while(scanf("%d%d",&m,&n)!=EOF)
	{
		for(int i=0;i<m;i++)
			for(int j=0;j<n;j++)
				cin>>a[i][j];
		memset(dp,0,sizeof(dp));
		for(int i=0; i<m; i++)
			dp[i][n-1] = a[i][n-1];
		for(int j=n-2; j>=0; j--)
		{
			for(int i=0; i<m; i++)
			{
				dp[i][j] = a[i][j];
				if(i>0 && i<m-1)
					dp[i][j] += min(min(dp[i][j+1],dp[i+1][j+1]),dp[i-1][j+1]);
				else if(i==0)
					dp[i][j] += min(min(dp[i][j+1],dp[i+1][j+1]),dp[m-1][j+1]);
				else if(i==m-1)
					dp[i][j] += min(min(dp[i][j+1],dp[ 0 ][j+1]),dp[i-1][j+1]);
			//	cout<<dp[i][j]<<" ";
			}
		//	cout<<endl;
		}
		int mini, mine = dp[m-1][0];
		for(int i=m-1; i>=0; i--)
		{
			if(mine >= dp[i][0])
			{
				mine = dp[i][0];
				mini = i;
			}
		}
		memset(num,0,sizeof(num));
		num[0] = mini;
		for(int j=1; j<n; j++)
		{
			int flag = 0;
			for(int i=0; i<m; i++)
			{
				if(mini==0 && i!=0 && i!=1 && i!=m-1)
					continue;
				if(mini==m-1 && i!=m-1 && i!=m-2 && i!=0)
					continue;
				if(mini>0 && mini<m-1 && i!=mini && i!=mini+1 && i!=mini-1)
					continue;
				if(dp[mini][j-1] - a[mini][j-1]==dp[i][j])
				{
					mini = i;
					num[j] =mini;
					flag =1;
				}
				if(flag)
					break;
			}
		}
		cout<<num[0]+1;
		for(int j=1;j<n;j++)
			cout<<" "<<num[j]+1;
			cout<<endl;
		cout<<mine<<endl;
	}
	return 0;
} 


相關文章