UVA116:多段图的最短路

UVA116

题解:

  • 参考刘汝佳的代码。每次从最后一列开始往前推。dp[i][j]表示从(i,j)到最后一列的整数和最小值。因为每次只能直行,右上,右下。所以dp[i][j] = max(dp[i][j+1],dp[i+1][j+1],dp[i-1][j+1])。
  • 但是事情没有这么简单因为第一行的上面是最后一行,最后一行的下面是第一行。所以这里我们再开一个数组row[3],记录3个行,所以dp[i][j] = max(dp[row[0]][j+1],dp[row[1]][j+1],dp[row[2]][j+1])。
  • 但是还没有结束,因为字典序要最小,所以对row排个序就解决了。
  • 求路线就是开个next数组,每次遇到更优路线记录一下。

代码:

#include <cstring>
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
int const N = 10 + 5;
int const M = 100 + 5;
int const inf = 0x7f7f7f7f;
int mp[N][M],dp[N][M],ne[N][M];  //dp[i][j]表示在(i,j)到终点的最小值
int n,m;
void solve(){
	int ans = inf,first;
	for(int j=m;j>=1;j--){
		for(int i=1;i<=n;i++){
			if(j == m)	dp[i][j] = mp[i][j];
			else{
				int row[3] = {i-1,i,i+1};
				if(i == 1)	row[0] = n;
				if(i == n)	row[2] = 1;
				sort(row,row+3);
				dp[i][j] = inf;
				for(int k=0;k<3;k++){
					int v = dp[row[k]][j+1] + mp[i][j];
					if(v < dp[i][j])	{dp[i][j] = v;	ne[i][j] = row[k];}
				}
			}
			if(j == 1 && dp[i][j] < ans)	{ans = dp[i][j];	first = i;}
		}
	}
	for(int i=first,j=1;j<=m;i=ne[i][j],j++)   //先next,在j++
		printf("%d%c",i,j!=m?' ':'\n');
	printf("%d\n",ans);
}
int main(){	
	while(~scanf("%d%d",&n,&m)){
		for(int i=1;i<=n;i++)
			for(int j=1;j<=m;j++)
				scanf("%d",&mp[i][j]);
		solve();
	}
	return 0;
}

 

posted @ 2019-02-22 17:15  月光下の魔术师  阅读(11)  评论(0)    收藏  举报