Uva 116 Unidirectional TSP (DP_记忆化搜索)


题目链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=114&page=show_problem&problem=52


题目大意给定一个n*m的矩阵,问从第一列走到最后一列经过的最小路径长度,方向有三个:右上,右,右下,第一行和最后一行是连通。在输出最小路径的同时输出经过哪些行,按字典序最小输出。


解题思路:记忆化搜索,模型很简单,就是从底向上,每次都找三个方向的最小值,关键是要输出路径,我是用一个path数组保存选择的方向。


测试数据:

3 3
1 2 3
1 2 3

1 2 3


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 10


代码:

#include <stdio.h>
#include <string.h>
#define MIN 40
#define MAX 200
#define INF 1000000000


int dir[3][2] = {{-1,1},{0,1},{1,1}};
int n,m,arr[MIN][MAX],vis[MIN][MAX];
int dp[MIN][MAX],path[MIN][MAX],minn,mini;


int Geti(int i) {

	if (i > n) i = 1;
	if (i < 1) i = n;
	return i;
}
int Dfs(int i,int j) {

	if (vis[i][j]) return dp[i][j];
	vis[i][j] = 1;
	if (j == m) {
		
		dp[i][j] = arr[i][j];
		return dp[i][j];
	}


	int tpmin = INF,tp;
	for (int k = 0; k < 3; ++k) {
		
		int ii = Geti(i + dir[k][0]);
		int jj = j + dir[k][1];
		


		tp = Dfs(ii,jj) + arr[i][j];

		if (tp < tpmin || tp == tpmin && ii < Geti(i + dir[path[i][j]][0])) {

			path[i][j] = k;
			tpmin = tp;
			dp[i][j] = tpmin;
		}
	}
	return dp[i][j];
}


int main()
{
	int i,j,k,tpi,tpj;


	while (scanf("%d%d",&n,&m) != EOF) {

		for (i = 1; i <= n; ++i)
			for (j = 1; j <= m; ++j)
				scanf("%d",&arr[i][j]);
		

		for (i = 1; i <= n; ++i)
			for (j = 1; j <= m; ++j)
				vis[i][j] = 0,dp[i][j] = path[i][j] = INF;
		minn = INF;
		for (i = 1; i <= n; ++i) {

			Dfs(i,1);
			if (dp[i][1] < minn) 
				minn = dp[i][1],mini = i;
		}


		printf(m == 1 ? "%d\n" : "%d ",mini);
		tpi = mini,tpj = 1;
		for (i = 1; i < m; ++i)  {

			k = path[tpi][tpj];
			tpi = Geti(tpi + dir[k][0]);
			tpj += dir[k][1];
			printf(i == m - 1 ? "%d\n" : "%d ",tpi);
		}
		printf("%d\n",minn);
	}
}

本文ZeroClock原创,但可以转载,因为我们是兄弟。

你可能感兴趣的:(测试,Path)