小胖办证

题目描述

xuzhenyi要办个签证。办证处是一座M层的大楼,1< =M< =100。
每层楼都有N个办公室,编号为1..N(1< =N< =500)。每个办公室有一个签证员。
签证需要让第M层的某个签证员盖章才有效。
每个签证员都要满足下面三个条件之一才会给xuzhenyi盖章:

  1. 这个签证员在1楼
  2. xuzhenyi的签证已经给这个签证员的正楼下(房间号相同)的签证员盖过章了。
  3. xuzhenyi的签证已经给这个签证员的相邻房间(房间号相差1,楼层相同)的签证员盖过章了。

每个签证员盖章都要收取一定费用,这个费用不超过1000000000。
找出费用最小的盖章路线,使签证生效

输入数据

第 1 行两个整数 M 和 N
接下来 M 行每行 N 个整数,第 i 行第 j 个数表示第 i 层的第 j 个签证员收取的费用。

输出数据

按顺序打出你经过的房间的编号,每行一个数。
如果有多条费用最小的路线,输出任意一条。

样例输入

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

样例输出

3
3
2
1
1

 解析:动态规划,移动方式,同一层移动和上下层房间号相同的移动

先计算,同一房间号的上下层之间的花费,然后,在同一层向右走更新dp,再向左走更新dp。

#include<iostream>
#include<math.h>
using namespace std;
int cost[105][505]; 
long dp[105][505];
struct Node{
	int x;
	int y;
};
Node path[105][505];//记录路径 

int main(){
	int m,n;
	cin>>m>>n;
	for(int i=1; i<=m; i++)
		for(int j=1; j<=n; j++)
			cin>>cost[i][j];
			
	for(int i=1; i<=m; i++)
		for(int j=1; j<=n; j++)
			dp[i][j] = 1e9 + 1;
			
	for(int j=1; j<=n; j++){
		dp[1][j]=cost[1][j]; //第一层 
		Node temp = {0,0};
		path[1][j] = temp;
	}
	
	for(int i=2; i<=m; i++){
		//从上到下 
		for(int j=1; j<=n; j++){
			dp[i][j] = dp[i-1][j] + cost[i][j];
			Node temp = {i-1, j};
			path[i][j] = temp;	
		}
		//从左到右 
		for(int j=2; j<=n; j++){
			if(dp[i][j-1]+cost[i][j]<dp[i][j]){
				dp[i][j]=dp[i][j-1]+cost[i][j];
				Node temp = {i, j-1};
				path[i][j] = temp;
			}
		}
		//从右到左 
		for(int j=n-1; j>0; j--){
			if(dp[i][j+1]+cost[i][j]<dp[i][j]){
				dp[i][j]=dp[i][j+1]+cost[i][j];
				Node temp = {i, j+1};
				path[i][j] = temp;
			}
		}
	}
	
	//找到花费最小的终点 
	Node end;
	end.x=m;
	long cost = 1e9 + 1;
	for(int j=1; j<=n; j++)
		if(dp[m][j]<cost){
			cost = dp[m][j];
			end.y = j;
		}

	int ans[1000];
	int k=0;
	Node cur = end;	
	//回溯路径 
	while(1){
		if(cur.x==0)
			break;
		ans[k++]=cur.y;
		cur=path[cur.x][cur.y];
	}
	for(int i=k-1; i>=0; i--)
		cout<<ans[i]<<endl;
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值