ural 1029. Ministry

翻译来自NOCOW

描述

Mr. F. 想让部长批阅签署一份文件。但只有当部长的下属部门核准后,部长才签署一份文件。部门是一座M层的建筑物,从地面开始数起为1到M层。1<=M<=100.每一层有N个房间(1<=N<=500),也是从1到N编号。每一个房间里有且只有一个官员。 一份文件要被部门签署,必须有至少一位(第M层建筑物里的)官员签署;一个官员必须至少满足以下一项条件才能签署一个文件:

条件a:该官员在第一层工作。

条件b:该文件已经被楼下同一间房的官员签署。

条件c:该文件已经被隔壁的官员签署(所谓隔壁,是指同一层,且房间号相差为1。)

每一个官员签署一份文件,收取一点费用,这个费用为不超过10^9的正整数。 请找出签署一份文件要付出的最少费用。

[编辑]输入格式

首行为2个整数,空格隔开。第一个数为M,表示M层;第二数为N,表示每层N个房间。 以下M行,每行N个整数,空格隔开,描述每间房子的官员签署一份文件收取的费用(第l行的第k个整数表示第l层的第k间房的费用)。

[编辑]输出格式

求出让文件顺利签署所经过的房间号,这必须是付款最少的路线。 假如有多个方案,输出任一个即可。

[编辑]Sample Input

3 4
10 10 1 10
2 2 2 10
1 10 10 10

[编辑]Sample Output

3 3 2 1 1

[编辑]Hint 提示

可以假设总是存在让文件签署的路子,费用总数不超过10^9


分析:记忆化搜索。

Code:

#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <vector>
#include <queue>
#include <cmath>
#include <map>
#include <set>
#define LL long long
#define pb push_back
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std;

const int inf=0x3f3f3f3f;
const int maxn=105;
int Map[maxn][maxn*5],dp[maxn][maxn*5],dir[maxn][maxn*5];
int n,m;

int dfs(int x,int y){
    if(y>m||y<1) return inf;
    if(x==1) return Map[x][y];
    if(dp[x][y]<inf) return dp[x][y];
    int tmp=dfs(x-1,y)+Map[x][y];
    if(tmp<dp[x][y]){
        dp[x][y]=tmp;
        dir[x][y]=-1;
    }
    tmp=dfs(x,y-1)+Map[x][y];
    if(tmp<dp[x][y]){
        dp[x][y]=tmp;
        dir[x][y]=-2;
    }
    tmp=dfs(x,y+1)+Map[x][y];
    if(tmp<dp[x][y]){
        dp[x][y]=tmp;
        dir[x][y]=2;
    }
    return dp[x][y];
}

void print(int x,int y){
    if(x==1) {
        if(n>1) printf("%d ",y);
        else printf("%d\n",y);
        return ;
    }
    if(dir[x][y]==-1) print(x-1,y);
    else if(dir[x][y]==-2) print(x,y-1);
    else if(dir[x][y]==2) print(x,y+1);
    if(x==n) printf("%d\n",y);
    else printf("%d ",y);
}

int main()
{
    scanf("%d %d",&n,&m);
    memset(dp,inf,sizeof(dp));
    memset(dir,0,sizeof(dir));
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            scanf("%d",&Map[i][j]);
        }
    }
    int pay=inf,id;
    for(int i=1;i<=m;i++){
        int tmp=dfs(n,i);
        if(tmp<pay){
            pay=tmp;
            id=i;
        }
    }
    print(n,id);
    return 0;
}


你可能感兴趣的:(ural 1029. Ministry)