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;
}