[算法课] 小偷问题 原创
算法标签 递归
题目来源 算法课
题目简介
思路
很明白的思路
一个小偷从N个数列当中获取值,但是必须从左往右固定顺序
精简一下,就是一个数值序列,从左往右,获取任意长度下的最小和
我们可以使用NXN暴力比对,当然这里我们使用递归也差不多,N个数字,也就是可能存在的和的数字数量实际不定,我们对N个数字都递归,直到获取到第N个数字位置,过程比对
代码
更新
之前理解错了题目的思路,以为是强制从左往右
如果是随便在中间插入的话,背包思路似乎不使用,我们直接暴力
#include<iostream>
#include<algorithm>
using namespace std;
const int N=1e9+10;
const int MaxArrSpace = 1010;//数组空间
typedef long long LL;
int a[MaxArrSpace];
int minn=N;//最小值
int n;
void dfs(int u,int sum)//u 当前选择的第几个,sum是总和
{
if(u==n)return ;
dfs(u+1,sum+a[u]);//递归到下一个
minn=min(minn,sum+a[u]);//更新
}
int main()
{
cin>>n;
for(int i=0;i<n;i++)cin>>a[i];
for(int i=0;i<n;i++)dfs(i,0);
cout<<minn;
return 0;
}
需要注意的问题
但这里出现一个问题
如果所有的值都是正整数
如果我们将
cout<<sum+a[u]<<" ";
minn=min(minn,sum+a[u]);
改为
cout<<sum<<" ";
minn=min(minn,sum);
左侧是cout<<sum+a[u]<<" “; minn=min(minn,sum+a[u]);
右侧是cout<<sum<<” "; minn=min(minn,sum);
我们可以发现,针对右侧我们是少一个值的,而剩下的一个值又因为sum初始值是0的原因,造成了最小值在全是正数的情况下是0
那么,为什么在很多非纯正数的数据是正常的呢?
因为一但数值存在负数,那么数值最小值肯定是负数,不可能是0
右侧是
cout<<sum+a[u]<<" ";
minn=min(minn,sum+a[u]);
左侧的是
cout<<sum<<" ";
minn=min(minn,sum);
我们可以很清晰的发现两者的区别
那么事实上这里的问题出现在哪里呢?
逻辑代码
测试数据
我们检查这里会发现,事实上,我们先递归到了最高层得到sum -2,-2事实上是N个数字相加所得的结果
他是怎么出来的呢?
程序从0递归到最高层n-1,退出,此时开始回溯,将得到的答案输出,但这个时候,我们的回溯到底检查,发现第一层是单纯的sum=0,即sum得初始值,检查所有的值,发现都是从a[0]到a[n-1]累加,当前得a[u]却并没有获取!
我们可以直接观察数值
推测问题在这一行
dfs(u+1,sum+a[u]);
u+1,但是sum的a[u]却实际是前一个u的值,并没有即时更新
如果我们不更新n个值,而是n+1个值,我们就会发现a[n-1],即第n个值的出现
如果这样写的话,我们要排除的问题就是第一个值是废的
但我们不能盲目的增设初始值
一旦这样更改就会出现累加错误的情况
即给了初始值之后,下一次执行累加由增加了初始值a[0],a[0]被累加了两次
或者,我们换一个写法
这次我们在递归之前直接更新,输出
很清楚明了的发现,此时的第一次的sum其实是没有任何其他值,只有自身的初始值
要更改的方式也相同
即增添当前需要的a[u]
所以现在我们总结一下
为什么在很多非纯正数的数据是正常的呢?
因为一但数值存在负数,那么数值最小值肯定是负数,不可能是0
那么事实上这里的问题出现在哪里呢?
dfs(u+1,sum+a[u]);
u+1,但是sum的a[u]却实际是前一个u的值,并没有即时更新
如果我们不更新n个值,而是n+1个值,我们就会发现a[n-1],即第n个值的出现
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现