您的位置:首页 > 其它

矩阵迷宫 HihoCoder - 1702 DP解法

2018-03-30 04:36 274 查看

#1702 : 矩阵迷宫

时间限制:10000ms单点时限:1000ms内存限制:256MB

描述

给定一个NxN的方格矩阵迷宫,每个格子中都有一个整数Aij。最初小Hi位于迷宫左上角的格子A11,他每一步可以向右或向下移动,目标是移动到迷宫的出口——右下角ANN。  小Hi需要支付的代价包括路径中经过的所有格子中的整数之和,以及改变移动方向需要支付的代价。  小Hi第一次改变方向的代价是1,第二次的代价是2,第三次的代价是4,…… 第K次的代价是2K-1。  请你帮小Hi算出要离开迷宫代价最小的路径,并输出要支付的代价。

输入

第一行一个整数N。  (1 ≤ N ≤ 100)  以下N行每行N个整数,代表矩阵A。  (1 ≤ Aij ≤ 100)

输出

从左上角到右下角路径的最小的代价。样例输入
3
1 3 5
1 1 2
5 1 1
样例输出
9
题意:求从左上角到右下角(只能向右或者向下走)经过的路上的最小代价和(包括改变方向的代价,和经过的坐标的代价),
第一次改变方向的代价是1,第二次的代价是2,第三次的代价是4,…… 第K次的代价是2K-1。 
思路:因为只能向右或者向下走,所以要往动态规划上想,坐标,方向,和拐弯的次数。

dp【i】【j】【k】【h】表示到坐标(i,j)这个位置,并且当前的方向为k(0表示下,1表示右),已经转弯h次的最小代价。
(这个代价先不包括h次转弯,最后再算)。
一共分为四种情况,面朝下向下走,面朝右向下走,面朝下向右走,面朝右向右走;

计算到dp

[2][20]为止, 因为n*n的图,不能往回走,所以一定经过2*n-1个坐标,这些坐标代价最大2*100*100,所以拐弯代价不会很大,及2*20就远远大于坐标代价的极限值了。数组最后一维算到20足以。
代码:#include <iostream>
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<queue>
#include<algorithm>
#define inf 0x3f3f3f3f
#define N 200500
#define LL long long
#define mem(a,b) memset(a,b,sizeof(a));
using namespace std;
int a[105][105];
int dp[105][105][2][23];
int minn(int x,int y)
{
return x>y?y:x;
}
int main()
{
mem(dp,inf);//初始化为极限大
int n;
scanf("%d",&n);
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
scanf("%d",&a[i][j]);
dp[1][1][1][0]=dp[1][1][0][0]=a[1][1];//初始坐标
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
for(int h=0; h<20; h++)//开始状态转移
{
if(i<n)//如果不为最后一行,那么就可以往下走
{
if(dp[i][j][0][h]!=inf)//当前位置代价不为极限大的话
dp[i+1][j][0][h]=minn(dp[i+1][j][0][h],dp[i][j][0][h]+a[i+1][j]);//面朝下向下走一格,不需要转向
if(dp[i][j][1][h]!=inf)
dp[i+1][j][0][h+1]=minn(dp[i+1][j][0][h+1],dp[i][j][1][h]+a[i+1][j]);//面朝右向下走一格,要转向
}
if(j<n)//如果可以向右走的话
{
if(dp[i][j][0][h]!=inf)
dp[i][j+1][1][h+1]=minn(dp[i][j+1][1][h+1],dp[i][j][0][h]+a[i][j+1]);//面朝下向右走,要转向
if(dp[i][j][1][h]!=inf)
dp[i][j+1][1][h]=minn(dp[i][j+1][1][h],dp[i][j][1][h]+a[i][j+1]);//面朝右向右走,不用转向
}
}
int ans=inf;
for(int i=0; i<=20; i++)
{
ans=minn(ans,dp

[0][i]+(1<<i)-1);//遍历终点的所有情况,存最小值
ans=minn(ans,dp

[1][i]+(1<<i)-1);//最后计算拐弯i次的代价
}
printf("%d\n",ans);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: