题目:
先发代码如下:
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
char c[20];
LL ans=0;
//n:1号操作剩余次数 m:2号操作剩余次数
int n,m;
void dfs(int i,LL v){
int x=c[i]-'0';
if(c[i]){
//应该使用的操作次数
int t=min(n,9-x);
n-=t;
dfs(i+1,v*10+x+t);
//回溯
n+=t;
//考虑操作2是否能够使用
if(m>x){
m-=x+1;
dfs(i+1,v*10+9);
//回溯
m+=x+1;
}
}
else{
//答案取max
ans=max(ans,v);
}
}
int main()
{
scanf("%s%d%d",c,&n,&m);
dfs(0,0);
printf("%lld\n",ans);
return 0;
}
算法个人理解:
刚开始看这个代码的时候,说实话我没头绪,看不懂,特别是那个“v*10+x+t”,但是我最后还是理解了,其实就是前一位的乘10再加后一位的数,再加可以加的最大数(按题目)。
除了上面这个,还有n-=t;,n+=t;,m-=x+1;,m+=x+1;,其实我们可以从现实方面看问题,递归是什么,按照树的思想来看,树的一个分叉就是递归,要回到分叉前的状态,就要保证所有的条件不变,所以每次递归之后要恢复n,m的值,给前一步的递归留个活路。n-=t为后面的递归服务,n+=t为前面不同方向的递归服务。
先把1操作给完成,在执行2操作,然后撤销一个1操作,执行2操作······
我对递归的看法是:如果要想很好理解,正向构建函数,然后递归的时候把它当个包直接用就行,不用思考每个步骤,只要记得这个部分是干嘛用的,递归调用,然后怎么递归怎么调用都不用管,一定要想办法让自己理解,然后才能谈记忆!!!