題意:找最短路,知道三種行走方式,給出圖,求出一條從左邊到右邊的最短路,且字典序最小,
求出最短路徑實例分析
。用dp記憶化搜索的思想來考慮是思路很清晰的,但是困難在如何求出字典序最小的路。
因為左邊到右邊的字典序最小就必須從左邊開始找,于是我們可以換個思路,dp時從右邊走到左邊,這樣尋找路徑就可以從左向右了。
代碼:
/*
* Author: illuz
* Blog: http://blog.csdn.net/hcbbt
* File: uva116.cpp
* Create Date: 2013-09-20 20:56:07
* Descripton: dp, memorial
*/
#include
#include
using namespace std;
const int MAXN = 102;
int dis[MAXN][MAXN], map[MAXN][MAXN], n, m;
int cg(int x) {
if (x == 0) x = n;
else if (x == n + 1) x = 1;
return x;
}
int dp(int x, int y) {
x = cg(x);
if (dis[x][y] != -0xffffff) return dis[x][y];
return dis[x][y] = map[x][y] + min(min(dp(x - 1, y + 1), dp(x, y + 1)), dp(x + 1, y + 1));
}
void print(int x, int y) {
if (y < m)
printf("%d ", x);
else {
printf("%d\n", x);
return;
}
int a[3] = {cg(x - 1), cg(x), cg(x + 1)};
sort(a, a + 3);
int tt = dis[x][y] - map[x][y];
if (tt == dis[a[0]][y + 1])
print(a[0], y + 1);
else if (tt == dis[a[1]][y + 1])
print(a[1], y + 1);
else
print(a[2], y + 1);
}
int main() {
while (scanf("%d%d", &n, &m) != EOF) {
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++) {
scanf("%d", &map[i][j]);
if (j == m) dis[i][j] = map[i][j];
else dis[i][j] = -0xffffff;
}
int Min = 0xffffff, t, rx, ry;
for (int i = 1; i <= n; i++) {
t = dp(i, 1);
if (t < Min)
rx = i, Min = t;
}
print(rx, 1);
printf("%d\n", Min);
}
return 0;
}