算法分析 机器人收集硬币 硬币行问题

一、实验内容及目的

1.实验内容
  机器人收集硬币内容:
     几个硬币被放置在n×m板的单元格中。位于棋盘左上角单元格的机器人需要收集尽可能多的硬币并将它们带到右下角单元格。在每一步中,机器人可以将一个单元格向右移动或从其当前位置向下移动一个单元格。
     输入n,m和n行m列的矩阵,矩阵用来表示单元格中是否有硬币存在,有硬币表示为1,没有硬币表示为0。输出机器人收集硬币的最大数量。
   硬币行问题内容:
    有一行n个硬币,其值是一些正整数C1,C2,C3…Cn,不一定是不同的。目标是捡起最大金额的钱,但约束条件是不能捡起初始行中相邻的两个硬币。
输入两行,第一行是n,表示硬币的数量,第二行是n个整数,表示n个硬币的币值;输出其中最大数额的钱。
2.实验目的
    针对实验题目中的问题,选择时空权衡或动态规划的算法设计策略进行设计,使用高级程序设计语言进行编码和调试,并进行效率分析。

二、实验方案

1.机器人收集硬币
   ① 分析:
     问题的意思是,在 n × m 格木板上有一些硬币,硬币个数最多为一个。现在机器人从左上角出发至右下角,每次只能右移或下移一格,求机器人最多收集多少硬币。设有硬币的格子为 1,用数组 Arr[ n ][ m ] 保存地图值;令截止到达第 i 行第 j 列收集的最多硬币数为 F(i,j)
     现在我们来考虑一般情况,对于每个格子我们有两种到达方式:从左边过来或从上边下来。
     从左边过来:那么收集的最多硬币数 F(i,j)= F(i,j - 1)+ Arr[ i ][ j ]
     从上边下来:那么收集的最多硬币数 F(i,j)= F(i - 1,j)+ Arr[ i ][ j ]
     此时我们就得到了递推方程:
     F(i,j)= max{F(i,j - 1),F(i - 1,j)} + Arr[ i ][ j ];
     退出条件(特殊情况):
          当 i = 1 时,无法从上边下来,此时我们将 F(0,j)= 0;
          当 j = 1 时,无法从左边过来,此时我们将 F(i,0)= 0;
     如下图,这样就满足 F(i,j)= max{F(i,j - 1),F(i - 1,j)}+ Arr[ i ][ j ]
     算法思想:动态规划
以样例分析:
     通过回溯计算过程可以得到最优路径:
     如果F(i-1,j)>F(i,j-1),到达单元格(i,j)的最优路径肯定是来自其上方相邻单元格;
     如果F(i-1,j)<F(i,j-1),达到单元格(i,j)的最优路径肯定是来自其左方的相邻单元格;
     如果F(i-1,j)=F(i,j-1),达到单元格(i,j)的景优路径可以来自上方相邻或左方相邻单元格。以下图为例,产生了两条不同的最优路径。如果忽略此类双解的情况,可以在O(n+m)时间内找到一条最优路径。
在这里插入图片描述
硬币分布状况:
在这里插入图片描述
数组图:
在这里插入图片描述

解:
在这里插入图片描述

② 算法伪代码:
在这里插入图片描述

2.硬币行问题
     ① 分析:
     问题的意思是,在原始位置互不相邻的条件下,所选硬币的总值最大。不能够相邻那么就考虑当前位的前两个数对应的最好状态+当前数,和当前数的前一个数的状态比较。设第 i 个硬币币值为 Ci,可选最大金额为 F(i)。
     现在我们来考虑一般情况,对于每个硬币 i 我们有两种选择:要或者不要。
     要第i个:那么可选硬币的金额 F( i ) = F( i - 2 ) + Ci
     不要第i个:那么可选硬币的金额 F( i ) = F( i - 1 )
     我们就得到了递推方程:
          F(n)= max{ F(n - 2)+ Ci , F(n - 1)}
     现在我们考虑一下退出条件(特殊情况): 当 n = 0 时,有 F(0)= 0; 当 n = 1 时,有 F(1)= C1; 这样就构建一个递归函数解题。
     算法思想:动态规划
以样例分析:
在这里插入图片描述

求解一排硬币5,1,2,10,6,2的过程如下所示。算法求得的最大金额为17

F[0]=0,F[1]=C1=5
在这里插入图片描述

F[2]=max{1+0,5}=5

在这里插入图片描述

F[3]=max{2+5,5}=7

F[4]=max{10+5,7}=15

在这里插入图片描述

F[5]=max{6+7,15}=15

在这里插入图片描述

F[6]=max{2+15,15}=17

在这里插入图片描述

② 算法伪代码
在这里插入图片描述

三、结果及分析
1.机器人收集硬币
① 测试数据
在这里插入图片描述

② 实验结果
在这里插入图片描述

③ 时间复杂度:O(n*m)
④ 空间复杂度:O(n*m)
2.硬币行问题
① 测试数据:
在这里插入图片描述

② 实验结果

在这里插入图片描述

③ 时间复杂度:O(n)
④ 空间复杂度:O(n)

四、总结
     经过此次实验,我对动态规划有了更深的了解。动态规划是一种在数学、计算机科学和经济学中使用的,通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。动态规划算法是通过拆分问题,定义问题状态和状态之间的关系,使得问题能够以递推(或者说分治)的方式去解决,它是一种灵活的方法,不存在一种万能的动态规划算法可以解决各类最优化问题,要实际问题实际分析。这次实验让我更加理解动态规划的思想,对算法知识的运用更加熟练,培养了我的思维能力和分析解决问题的能力。
五、参考文献及附录

1.机器人收集硬币
#include<stdio.h>
#include<iostream>
#include<string.h>
using namespace std;
int arr[1005][1005];        //建立一个map

int Max(int a, int b)       //求最大值
{
    return a > b ? a : b;
}

void MaxValue(int n, int m)         //逐行求出最优解
{
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++)
            arr[i][j] = Max(arr[i - 1][j], arr[i][j - 1]) + arr[i][j];
}

int main()
{
    memset(arr, 0, sizeof(arr));
    int n,m;
    cin>>n>>m;
    for (int i = 1; i <= n; i++)    //从元素位置 1 开始逐列(行)对齐
        for (int j = 1; j <= m; j++)
            cin>>arr[i][j];

    MaxValue(n, m);
    Cout<<arr[n][m]<<endl;    //最后一个即为最优解

    return 0;
}

2.硬币行问题
#include<stdio.h>
#include<iostream>
#include<string.h>
using namespace std;
int arr[10005];

int Max(int a, int b)                    //求最大值
{
    return a > b ? a : b;
}

void MaxValue(int n)
{
    arr[n] = Max(arr[n - 1], arr[n - 2] + arr[n]);
}

int main()
{
    memset(arr, 0, sizeof(arr));
    int n;
   cin>>n;
    for (int i = 1; i < n + 1; i++)
        cin>>arr[i];

    for (int i = 2; i < n + 1; i++)//从头开始找出每 i 个硬币的最大金额值
        MaxValue(i);

  cout<<arr[n]<<endl;

    return 0;
}

  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值