题目大意:给你两串数字a和b
让你重新排列第一串数字使得a比b小并且a要取到最大值
保证没有前导零
思路:一开始想着循环但是不会...
最终搜了一下答案写了dfs
思路就是一个数字一个数字的进行排列
如果排列的同一个位数数字正好对应b[i]的数字那么就继续排
如果同一个位数找不到比b[i]相等的时候就找比它小的数字排列了
并把剩下的数字进行从大到小进行排列(排列小的时候就已经比b小了,再怎么排都不会比b大)
最后输出答案即可
在这里要强调一下不能按字符串长度进行循环并dfs(会超时)
应该把每个数的个数数量存进去进行循环与dfs
最后记得剪枝回溯就好啦
具体看代码
AC代码:
#include <iostream> #include <string> #include <algorithm> using namespace std; string a,b; int v[19]= {0}; char ans[20]; bool cmp(char a,char b) { return a>b; } int len1; int ok=1; void dfs(int x) { if(x==len1&&ok) { for(int i=0; i<len1; i++)cout<<ans[i]; ok=0; return; } else if(!ok)return; for(int i=9; i>=0; i--) { if(v[i])//看这个数有没有被用过 { if(i+'0'==b[x])//如果等于最好,继续递归 { v[i]--; ans[x]=i+'0'; dfs(x+1); v[i]++; } else if(i+'0'<b[x])//如果小于说明已经没方法,是最优解了直接输出 { v[i]--; ans[x]=i+'0'; for(int k=9; k>=0; k--) { while(v[k]) { ans[++x]=k+'0'; v[k]--; } } if(ok) cout<<ans<<endl; ok=0; return; } } } return; } int main() { cin>>a>>b; len1=a.size(); int len2=b.size(); if(len1<len2) { sort(a.begin(),a.end(),cmp); cout<<a; } else { for(int i=0;i<len1;i++){ v[a[i]-'0']++; } dfs(0); } return 0; } /* 19875 19843 864791075345678672 234567890869429234 102 1000 2000000000001 2000000000000 */