您的位置:首页 > 其它

DP+路径 URAL 1029 Ministry

2015-05-11 11:39 369 查看
题目传送门

 /*
题意:就是从上到下,找到最短路,输出路径
DP+路径:状态转移方程:dp[i][j] = min (dp[i-1][j], dp[i][j-1], dp[i][j+1]) + a[[i][j];    (类似数塔问题)
关键在记录路径,可以用pre[x][y] = -1/0/1/2 区分,DFS回溯输出
详细解释:http://www.cnblogs.com/staginner/archive/2012/05/02/2479658.html
*/
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
#include <stack>
using namespace std;

const int MAXN = 1e2 + 10;
const int MAXM = 5e2 + 10;
const int INF = 0x3f3f3f3f;
int a[MAXN][MAXM];
int dp[MAXN][MAXM];
int pre[MAXN][MAXM];

void DFS(int x, int y)
{
if (pre[x][y] == -1)    {printf ("%d", y);    return ;}
if (pre[x][y] == 0)        DFS (x-1, y);
else if (pre[x][y] == 1)    DFS (x, y-1);
else    DFS (x, y+1);

printf (" %d", y);
}

int main(void)        //URAL 1029 Ministry
{
//freopen ("X.in", "r", stdin);

int n, m;
while (scanf ("%d%d", &n, &m) == 2)
{
memset (pre, -1, sizeof (pre));
memset (dp, 0, sizeof (dp));
for (int i=1; i<=n; ++i)
for (int j=1; j<=m; ++j)    scanf ("%d", &a[i][j]);

for (int i=1; i<=m; ++i)    {dp[1][i] = a[1][i];    pre[1][i] = -1;}
for (int i=2; i<=n; ++i)
{
for (int j=1; j<=m; ++j)    {dp[i][j] = dp[i-1][j] + a[i][j];    pre[i][j] = 0;}
for (int j=2; j<=m; ++j)
{
if (dp[i][j] > dp[i][j-1] + a[i][j])    {dp[i][j] = dp[i][j-1] + a[i][j];    pre[i][j] = 1;}
}
for (int j=m-1; j>=1; --j)
{
if (dp[i][j] > dp[i][j+1] + a[i][j])    {dp[i][j] = dp[i][j+1] + a[i][j];    pre[i][j] = 2;}
}
}

int mn = INF;    int x = n;    int y = 1;
for (int i=1; i<=m; ++i)
{
if (mn > dp
[i])    {mn = dp
[i];    y = i;}
}
//printf ("%d\n", mn);
DFS (x, y);    puts ("");
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: