您的位置:首页 > 其它

uva 116 (记忆化搜索)

2015-03-12 16:22 246 查看
题意:



如图,从左到右走,每次可以往左上(up)左(fo)左下(dn)走,当走到第一行或最后一行时可以如图穿越。

求一条权值最小的路径,并打印字典序最小的路径。

解析:

状态转移方程:

dp[ i ][ j ] = min( dp[ (i - 1 + m) % m ] [ j + 1 ], //up

dp[ i ] [ j + 1], //fo

dp[ ( i + 1) % m ] [ j + 1] ) //dn

字典序最小的路径也在记忆化搜索中更新,详见代码。

代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
#include <map>
#include <climits>
#include <cassert>
#define LL long long

using namespace std;

const int maxr = 10 + 10;
const int maxc = 100 + 10;
const int inf = 0x3f3f3f3f;

int g[maxr][maxc];
int path[maxr][maxc];
int dp[maxr][maxc];
int m, n;

int dfs(int i, int j)
{
if (n <= j)
return 0;
if (dp[i][j] != inf)
return dp[i][j];
int up = dfs((i - 1 + m) % m, j + 1);
int fo = dfs(i, j + 1);
int dn = dfs((i + 1) % m, j + 1);

int minn = up;
if (fo < minn)
minn = fo;
if (dn < minn)
minn = dn;

int dir = inf;
if (minn == up)
dir = min(dir, (i - 1 + m) % m);
if (minn == fo)
dir = min(dir, i);
if (minn == dn)
dir = min(dir, (i + 1) % m);

dp[i][j] = minn + g[i][j];
path[i][j] = dir;
return dp[i][j];
}

int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
#endif // LOCAL
while (scanf("%d%d", &m, &n) != EOF)
{
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
{
scanf("%d", &g[i][j]);
dp[i][j] = inf;
}
}
int ans = inf;
int pos = -1;
for (int i = 0; i < m; i++)
{
int t = dfs(i, 0);
if (t < ans)
{
ans = t;
pos = i;
}
}
printf("%d", pos + 1);
pos = path[pos][0];
for (int i = 1; i < n; i++)
{
printf(" %d", pos + 1);
pos = path[pos][i];
}
printf("\n%d\n", ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: