Mr. F. wants to get a document be signed by a minister. A minister signs a document only if it is approved by his ministry. The ministry is an M-floor building with floors numbered from 1 to M, 1<=M<=100. Each floor has N rooms (1<=N<=500) also numbered from 1 to N. In each room there is one (and only one) official.
A document is approved by the ministry only if it is signed by at least one official from the M-th floor. An official signs a document only if at least one of the following conditions is satisfied:
Mr. F. 想让部长批阅签署一份文件。但只有当部长的下属部门核准后,部长才签署一份文件。部门是一座M层的建筑物,从地面开始数起为1到M层。1<=M<=100.每一层有N个房间(1<=N<=500),也是从1到N编号。每一个房间里有且只有一个官员。
一份文件要被部门签署,必须有至少一位(M层建筑物里的)官员签署;一个官员必须至少满足以下一项条件才能签署一个文件:
a. the official works on the 1st floor;Each official collects a fee for signing a document. The fee is a positive integer not exceeding 10^9.
b. the document is signed by the official working in the room with the same number but situated one floor below;
c. the document is signed by an official working in a neighbouring room (rooms are neighbouring if they are situated on the same floor and their numbers differ by one).
条件a:该官员在第一层工作。
条件b:该文件已经被楼下同一间房的官员签署。
条件c:该文件已经被隔壁的官员签署(所谓隔壁,是指同一层,且房间号相差为1。)
You should find the cheapest way to approve the document.
每一个官员签署一份文件,收取一点费用,这个费用为不超过10^9的正整数。
请找出签署一份文件要付出的最少费用。
Input
The first line of an input contains two integers, separated by space. The first integer M represents the number of floors in the building, and the second integer N represents the number of rooms per floor. Each of the next M lines contains N integers separated with spaces that describe fees (the k-th integer at l-th line is the fee required by the official working in the k-th room at the l-th floor).
首行为2个整数,空格隔开。第一个数为M,表示M层;第二数为N,表示每层N个房间。 以下M行,每行N个整数,空格隔开,描述每间房子的官员签署一份文件收取的费用(第l行的第k个整数表示第l层的第k间房的费用)。
求出让文件顺利签署所经过的房间号,按顺序一行一个,这必须是付款最少的路线。 假如有多个方案,输出任一个即可。
Sample Input3 410 10 1 102 2 2 101 10 10 10Sample Output33211Hint 提示
You can assume that for each official there always exists a way to get the approval of a document (from the 1st floor to this official inclusively) paying no more than 10^9.
可以假设总是存在让文件签署的路子,费用总数不超过10^9
双向DP。楼下:f[i][j]=min(f[i][j],f[i-1][j]+room[i][j]);i为层数,j为房间数,room为本房间的价格
左隔壁:f[i][j]=min(f[i][j],f[i][j-1]+room[i][j]);
右隔壁:f[i][j]=min(f[i][j],f[i][j+1]+room[i][j]);
每一层正反各遍历一次。比较的时候要记录路径。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<stack>
using namespace std;
const int INF=0x7fffffff-1;
const int MAXM=103;
const int MAXN=503;
int room[MAXM][MAXN];//每个房间的花费
int f[MAXM][MAXN];//到这个房间的时候的最低消费
stack<int> s;//用来路径
typedef struct
{
int l,k;
}prior;
prior p[MAXM][MAXN];//保存来源房间的路径
int main()
{
//freopen("in.txt","r",stdin);
int m,n;
memset(p,0,sizeof(p));
scanf("%d %d",&m,&n);
for(int i=1;i<=m;i++)
{
for(int j=1;j<=n;j++)
{
scanf("%d",&room[i][j]);
f[i][j]=INF;
}
}
for(int i=1;i<=n;i++)//给第一层的赋初值
{
f[1][i]=room[1][i];
}
for(int i=2;i<=m;i++)
{
for(int j=1;j<=n;j++)
{
if(f[i-1][j]!=INF)
if(f[i][j]>f[i-1][j]+room[i][j])//和楼下的比较
{
f[i][j]=f[i-1][j]+room[i][j];
p[i][j].l=i-1;
p[i][j].k=j;
}
if(j>1&&f[i][j-1]!=INF)
if(f[i][j]>f[i][j-1]+room[i][j])//和左边隔壁比较
{
f[i][j]=f[i][j-1]+room[i][j];
p[i][j].l=i;
p[i][j].k=j-1;
}
}
for(int j=n-1;j>=1;j--)
{
if(f[i][j+1]!=INF)
if(f[i][j]>f[i][j+1]+room[i][j])//和右边隔壁比较
{
f[i][j]=f[i][j+1]+room[i][j];
p[i][j].l=i;
p[i][j].k=j+1;
}
}
}
int tk=1;
for(int i=2;i<=n;i++)//找出顶层中花费最少的房间
{
if(f[m][tk]>f[m][i])
{
tk=i;
}
}
int tl=m;
while(tl&&tk) //把路径压栈
{
s.push(tk);
int t1=p[tl][tk].l;
int t2=p[tl][tk].k;
tl=t1;
tk=t2;
}
printf("%d",s.top());
s.pop();
while(!s.empty()) //输出栈中的路径
{
printf(" %d",s.top());
s.pop();
}
return 0;
}