乘积最大(dfs+思维)

在这里插入图片描述
在这里插入图片描述
这道题以前我也遇见过,但是没搞明白,现在搞明白了:
这道题我当时一读题就想用dfs,但是有个问题就是我怎么把n-1个空位插k个乘号进去,并且最终判断最大值,因为dfs是要对每个位置都要枚举,并且前面的位置要占满;所以我就一直在想这个问题,结果没想出来,之后百度了一下,看了其他人的dfs,我感觉,那些人是真的大佬,我好菜。最后我还是看明白了,代码中count表示填的乘号的个数,res表示上几次段的数的乘积,index表示当前插入的下标,可以这样理解:
有了这个图才好理解下面说的话:
在这里插入图片描述
如果我要插入多个乘号,那么第一个乘号的范围就是[1,n-1],然后第二个乘号的范围就应该是[1,n],但是因为第二个的下限要受到第一个的制约,所以他本来的下限就应该是第一个的index+1;然后多个也照样这样理解;
现在的问题就是如何去把空位里面找出所有可能的填上k个乘号的填法,并且让每种填法比较;这里就需要知道这个问题:
因为dfs是对无间隙的遍历,且有一定范围;所以可以不难知道:每次遍历的范围是在[index+1,n-k+count];这里可以用笔算一下
这样每次dfs的时候只需要把前面的范围的值算出来之后传递给后面的dfs就可以解决这个问题了;如果仔细用脑袋想一下,也应该是这样的(把每次放置的位置所隔开的数都算出来,然后dfs(这个想法我挺佩服那些大佬的));
所以按照这种思路dfs就OK了:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll book[1000];
ll n,k,Max;
string s;
ll a[100];
void dfs(ll count,ll res,ll index){
	if(count==k){//当填够k个的时候
		ll num=0;
		  for(int i=index+1;i<=n;i++){//计算余下的数(如果越界就表示没有)
		  	  num=num*10+a[i];
		  }
		  Max=max(Max,res*num);
		  return ;
	}
	for(int i=index+1;i<=n-k+count;i++){//这里就是上面说的每个能走到的最大下标(当然如果越界了就不会计算下面的了)
		ll num=0;
		   for(int j=index+1;j<=i;j++){//这里就是把分段的可能性都计算(一个dfs一个可能性)
		   	num=num*10+a[j];
		   }
		   dfs(count+1,res*num,i);//这里是把上回的分段结果乘上res传给下一个dfs
	}
}
int main(){
	scanf("%lld %lld",&n,&k);
	cin>>s;
	for(int i=0;i<s.length();i++) a[i+1]=s[i]-'0';//这里初始化下标是从1开始的!!!
	dfs(0,1,0);//表示还没有填res=1是为了后面的计算
	printf("%lld\n",Max);
	return 0;
} 
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值