Uva116单向TSP

题意:给定一个n*m的矩阵,要求从第一列的任何一行出发,每次沿右或右下或右上到达后面一列,最后到第m列,要求经过的整数之和最小,如果多解要求是解的行字典序最小的。矩阵是环形的,即第一行的上一行是最后一行,最后一行的下一行是第一行。
思路:
逆向递推。定义状态:d[ i ][ j ] 为(i , j )到最后一列的最小和。边界条件是最后一列,d[ i ][ n] = table[ i ][ n ], 1 <= i <= n;从后往前,依次枚举当前列,每次有 3 种决策,右,右上,右下,选择代价最小的并记录路径。路径记录用 next[ i ][ j ] 表示(i ,j)的下一个决策行,如; next[ 2][ 1 ] = 3;说明(2,1)的下一个最优决策是(3,2)。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int INF = 1<<30;
int table[11][105] , d[11][105] , nextr[11][105];
int main()
{
	int r,c;
	//freopen("in.txt","r",stdin);
	while(scanf("%d %d",&r,&c) == 2){
		
		for(int i = 1; i <= r; ++i)
			for(int j = 1; j <= c; ++j)
				scanf("%d",&table[i][j]);
				
		int ans = INF, first;
		for(int j = c; j >= 1; --j){
			for(int i = 1; i <= r; ++i){
				if(j == c) d[i][j] = table[i][j]; // 边界条件 
				else {
					int rows[3] = { i-1, i, i+1 };
					if(i == 1) rows[0] = r;
					if(i == r) rows[2] = 1;
					sort(rows,rows+3);
					d[i][j] = INF;
					for(int k = 0; k < 3; ++k){
						int v = d[rows[k]][j+1] + table[i][j];
						if(v < d[i][j]) { d[i][j] = v; nextr[i][j] = rows[k]; }
					}
				}
				if(j == 1&&ans > d[i][j]) { ans = d[i][j]; first = i; }
			}
		}
		printf("%d",first);
		int i,j;
		for(i = nextr[first][1], j = 2; j <= c; i = nextr[i][j], ++j){
			printf(" %d",i);
			//if(j < c) printf(" ");
		}
		printf("\n%d\n",ans);
	}
	
	return 0;
}


猜你喜欢

转载自blog.csdn.net/CY05627/article/details/88343108
116
TSP