UVA116 Unidirectional TSP

来源:互联网 发布:银行卡余额查询软件 编辑:程序博客网 时间:2024/05/16 11:24

一. Vjudge链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?OJId=UVA&probNum=116

二. 题目大意:给一个矩阵,让你从左边走到右边,每次只能走右,右上,右下。从第一行走右上到最后一行,从最后一行走右下到第一行,求最小的路径长度(每次走过一个格子,路径增加格子里面的数),并输出最小字典序的路径(从第一列到最后一列关于行的路径)。

三. 思路:本来以为是DP水题,3个状态,上中下取最小,扫一遍就完了,没想到它弄了个字典序最小输出,这里指的是先比较第一个,再比较第二个。因此一定要从后向前扫,每次取最小,不能从前向后扫。(这个不知道为什么,留待以后补充。)因为它是环形的,2条路最小值一样,其中一条全部往右走,如果有一条路从第一个跳到了最后一个的话,从前往后扫会取那条中间的路,但是这样是错误的,因为会比较先输出的,因此要取那条跳到最后一个的路。

四. 代码:

#include <iostream>#include <cstdio>#include <queue>#include <cstring>#include <cmath>#include <algorithm>#include <stack>using namespace std;const int MAX_N = 128,          MAX_M = 15,          INF = 0x3f3f3f3f;int dp[MAX_M][MAX_N], row, col,    Next[MAX_M][MAX_N];int getMin(int i, int j){    j = j+1;//注意我一进入就加上1,以后不用重复写    int up, mid, down, idx, res;    mid = i;    up = (i-1 == 0? row:i-1);    down = (i+1 > row? 1:i+1);    idx = INF;    if(dp[mid][j] <= dp[up][j] && dp[mid][j] <= dp[down][j])        res = dp[mid][j], idx = min(idx, mid);    if(dp[up][j] <= dp[mid][j] && dp[up][j] <= dp[down][j])        res = dp[up][j], idx = min(idx, up);    if(dp[down][j] <= dp[mid][j] && dp[down][j] <= dp[up][j])        res = dp[down][j], idx = min(idx, down);    Next[i][j-1] = idx;    return res;}int main(){    //freopen("in.txt", "r", stdin);    int i, j;    while(~scanf("%d %d", &row, &col)){        for(i = 1; i <= row; i++)            for(j = 1; j <= col; j++)                scanf("%d", &dp[i][j]);        for(j = col-1; j >= 1; j--)            for(i = 1; i <= row; i++)            dp[i][j] += getMin(i, j);        int res = INF, idx;        for(i = 1; i <= row; i++)            if(res > dp[i][1])                res = dp[i][1], idx = i;        printf("%d", idx);        for(i = 1; i < col; i++){            idx = Next[idx][i];            printf(" %d", idx);        }        printf("\n%d\n", res);    }    return 0;}


0 0
原创粉丝点击