目录
1.最大数字
1.问题描述
给定一个正整数 N NN 。你可以对 N NN 的任意一位数字执行任意次以下 2 种操 作:
将该位数字加 1 。如果该位数字已经是 9 , 加 1 之后变成 0 。
将该位数字减 1 。如果该位数字已经是 0 , 减 1 之后变成 9 。
你现在总共可以执行 1 号操作不超过 A AA 次, 2 号操作不超过 B BB 次。 请问你最大可以将 N NN 变成多少?
2.输入格式
第一行包含 3 个整数: N , A , B N, A, BN,A,B
3.输出格式
一个整数代表答案。
4.样例输入
123 1 2
5.样例输出
933
6.数据范围
对于30 % 30\%30% 的数据, 1 ≤ N ≤ 100 ; 1 \leq N \leq 100;1≤N≤100;0 ≤ A , B ≤ 10 0 \leq A, B \leq 100≤A,B≤10。
对于 100 % 100 \%100% 的数据, 1 ≤ N ≤ 1 0 17 ; 0 ≤ A , B ≤ 100 1 \leq N \leq 10^{17} ; 0 \leq A, B \leq 1001≤N≤10
17
;0≤A,B≤100
7.原题链接
2.解题思路
N的范围为1e17,看似很大但其实只要考虑这17位,所以可以用暴力深搜找答案。
整个数左到右依次判断,从最左边开始枚举,我们无需关注后面的数,要利用自己的1
号操作和2
号操作保证当前这个数位的数一定要尽可能最大,
首先两个操作不可混用,因为它们是抵消的效果,所以要么对这个数全使用1
操作,要么2
操作。假设某个数位的值为x
,首先考虑1
号操作,使用后可以让该数位变大,出于贪心考虑,我们想让它变成9,先判定能不能让他变成9,如果不能就全用上,如果能,就减去所用的次数。再考虑2号操作,如果能将数变9就用,如果变不了宁愿不用。
在深搜dfs
的过程中,参数记录遍历到第几个数位以及此时累计的和,当搜索完所有数位后,将此时的和与答案进行一个取max
,最后的值则为答案。
则这一题可以有字符串和数组两种不同的解法,字符串好定位,而数组则便于计算但得记录数量积,在这里两种方法都用上。
1.字符串的dfs(深搜)函数
char a[20]; //N最多17位,我这里定为20位
typedef long long ll;//定义 long long
ll b,c,ans=0;//这里的ans 为最终输出的值
void dfs(int i,ll v,ll b,ll c){
int x=a[i]-'0';//将字符转化为数
ans=max(v,ans);//交换,达到最终结果
if(a[i]){ //如果a[i]还有,不为0;
if(b>9-x){
ll r=b-(9-x);
dfs(i+1,v*10+9,r,c);
}else {
dfs(i+1,v*10+b,0,c);
}
if(c!=0){
if(c>=x+1){
int k=c-(x+1);
dfs(i+1,v*10+9,b,k);//判断,深搜,递归,详细思路已在上言
}
}
}
}
1.2 总代码(字符串版)
#include <iostream>
#include <algorithm>
#include <vector>
#include <math.h>
using namespace std;
char a[20]; //N最多17位,我这里定为20位
typedef long long ll;//定义 long long
ll b,c,ans=0;//这里的ans 为最终输出的值
void dfs(int i,ll v,ll b,ll c){
int x=a[i]-'0';//将字符转化为数
ans=max(v,ans);//交换,达到最终结果
if(a[i]){ //如果a[i]还有,不为0;
if(b>9-x){
ll r=b-(9-x);
dfs(i+1,v*10+9,r,c);
}else {
dfs(i+1,v*10+b,0,c);
}
if(c!=0){
if(c>=x+1){
int k=c-(x+1);
dfs(i+1,v*10+9,b,k);//判断,深搜,递归,详细思路已在上言
}
}
}
}
int main(){
scanf("%s%d%d",&a,&b,&c);
dfs(0,0,b,c);
cout<<ans<<endl;
return 0;
}
2. 数组的深搜dfs函数
long long a,ans=1;
long long maxx=0;
void dfs(long long a,long long ans,long long b,long long c){
if(ans==0){
maxx=max(a,maxx);
return ;
}
int d=a/ans%10;
if(b>9-d){
int r=b-(9-d);
dfs(a+(9-d)*ans,ans/10,r,c);
}else {
dfs(a+b*ans,ans/10,0,c);
}
if(c!=0){
if(c>=d+1){
int r=c-(d+1);
dfs(a-d*ans+9*ans,ans/10,b,r);
}
}
}
while(a){ //要在这里将ans,即数量积记录下来。
a/=10;
ans*=10;
}
2.2总打码(数组版)
#include <iostream>
#include <algorithm>
#include <vector>
#include <math.h>
using namespace std;
long long a,ans=1;
long long maxx=0;
void dfs(long long a,long long ans,long long b,long long c){
if(ans==0){
maxx=max(a,maxx);
return ;
}
int d=a/ans%10;
if(b>9-d){
int r=b-(9-d);
dfs(a+(9-d)*ans,ans/10,r,c);
}else {
dfs(a+b*ans,ans/10,0,c);
}
if(c!=0){
if(c>=d+1){
int r=c-(d+1);
dfs(a-d*ans+9*ans,ans/10,b,r);
}
}
}
int main(){
long long b,c;
cin>>a>>b>>c;
long long t=a;
while(a){
a/=10;
ans*=10;
}
dfs(t,ans/10,b,c);
cout<<maxx<<endl;
return 0;
}
以上就是这一题的个人详解,主要考的是dfs深搜,暴力就够了,希望对大家有所帮助!