dfs对于大部分初学者都是一个很抽象的搜索方法,它算是暴力枚举,但是并没有暴力枚举如此直观,理解起来也比暴力枚举难不少。这篇文章主要针对与近期蓝桥杯比赛中做到的一个题目,来发表一下自己对dfs的理解。
题目在这
首先拿到这个题目我个人是首先想到贪心的,因为我们想最好能让最大数位的数字变成9,不然就让最大数位的数字尽量的大,但是显然有个问题,从逻辑上来讲,因为a,b两个操作我们无法确定优先使用哪一种一定可以得到最大的数,比如4111,如果a=5,b=5,我们如果按照a优先来算可以得到优解为9999,但是如果按照b优先我们就得不到,要知道,每一位数字都需要考虑是a优先还是b优先,因此时间复杂度为2的n次方,显然很炸。因此我们会采用dfs+贪心的策
略深度搜索每一种可能的最大值。
算法思想:我们首先对于a操作,深度搜索,保证每一位数字都是只是用a操作下的最大值,然后我们再去深度搜索b操作,如果这个数位用b操作,看会不会得到更优解,当然此时对于当前位置后面的数,dfs会自动再去重复上边的操作(先a,后b)这样去递归搜索。
总结下来,dfs搜索的本质其实就是:先a后b,不断循环更新当前的数,即使使用b操作更改了当前数位,后边的数位仍然是先a后b去操作。
当然这个题说的是最多使用a次1操作,b次2操作,所以这两次操作不一定要做完,只要能保证到达最大即可。
代码如下:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
string s;
ll a,b;
ll ans;
void dfs(ll x,ll res){
ll t=s[x]-'0';
if(s[x]){
ll c=min(a,9-t);
a-=c;
dfs(x+1,res*10+t+c);
a+=c;
if(t<b){
b=b-(t+1);
dfs(x+1,res*10+9);
b+=(t+1);
}
}
else {
ans=max(ans,res);
}
}
void solve(){
cin>>s;
cin>>a>>b;
dfs(0,0);
cout<<ans;
}
int main(){
solve();
return 0;
}