Bootstrap

青蛙过桥——动态规划

问题:

一座长度为n的桥,起点的一端坐标为0,且在整数坐标i处有a[i]个石头【0<=a[i]<=4】, 一只青蛙从坐标0处开始起跳,一步可以跳的距离为1或2或3【即每一步都会落在整数点处】, 青蛙落在i处会踩着该点的所有石头,求青蛙跳出这座桥最少踩多少个石头?

输入:

第一行整数n(<=150),接着下一行会有n+1个由空格隔开的整数,即桥上各个坐标处石头数量。

输出:

输出踩着最少石头个数

样例:

input:

10
1 2 1 3 0 3 1 2 1 1 2

output:
4

代码

#include<iostream>
using namespace std;
int stone(int a[], int n)
{
int *m = new int[n+1];

//m[i]表示青蛙到达坐标为i的点最少需要踩的石头数
for(int i=0; i<=n;i++)
{
if(i==0)m[i]=a[i];

//当在坐标为0的点时,最少需要踩的石头数( m[0] )即此坐标的石头数( a[0] )
else if(i==1)m[i]=m[i-1]+a[i];

//青蛙要到达坐标为1的点只能通过在坐标为0的点跳1距离到达

//此时青蛙到达坐标为i的点最少需要踩的石头数( m[1] )为青蛙到达坐标为0的点最少需要踩的石头数0( m[0] )+1点石头数( a[1] )
else if(i==2)
{
m[i]=m[i-2]+a[i];
if(m[i-1]+a[i]<m[i])m[i]=m[i-1]+a[i];
}

//到达坐标为2的点可以从坐标为0的点跳2距离到达,也可以从坐标为1的点跳1距离到达。

//相应地,此时青蛙到达坐标为i的点需要踩的石头数( m[2] )有两种取值:

1.青蛙到达坐标为0的点最少需要踩的石头数( m[0] )+2点石头数( a[2] );

2.青蛙到达坐标为1的点最少需要踩的石头数( m[1] )+2点石头数( a[2] )

由于是求最少石头数,所以取小的值作为m[i]的结果,即m[i]=min{  m[0]+a[2] , m[1]+a[2] }
else
{
m[i]=m[i-3]+a[i];
if(m[i-2]+a[i]<m[i])m[i]=m[i-2]+a[i];
if(m[i-1]+a[i]<m[i])m[i]=m[i-1]+a[i];
}

//到达坐标i(i>3)的点,可从坐标为i-3的点跳3距离到达,也可以从坐标i-2的点跳2距离到达,还可以从坐标i-1的点跳1距离到达。

//相应地,此时青蛙到达坐标为i的点需要踩的石头数有三种取值:

1.青蛙到达坐标为i-3的点最少需要踩的石头数( m[i-3] )+i点石头数( a[i] )

2.青蛙到达坐标为i-2的点最少需要踩的石头数( m[i-2] )+i点石头数( a[i] )

3.青蛙到达坐标为i-1的点最少需要踩的石头数( m[i-1] )+i点石头数( a[i] )

由于是求最少石头数,所以取小的值作为m[i]的结果,即m[i]=min{  m[i-3]+a[i] , m[i-2]+a[i] , m[i-1]+a[i] }
}


int min=m[n-2];
for(int j=n-2;j<=n;j++)
if(m[j]<min)min=m[j];

//青蛙跳的距离可为1、2、3,则青蛙要跳出桥,只能从坐标为n、n-1、n-2的点跳出,到达这三个点最少需要踩的石头数的最小值( min{ m[n], m[n-1], m[n-2] } ),即为青蛙跳出桥需要踩的最少石头数


return min;
}


int main()
{
int n;
cin>>n;
int*a=new int[n+1];
for(int i=0;i<=n;i++)
cin>>a[i];
cout<<stone(a,n);
}

;