题目
考虑两个n位的十进制正整数A和B,都没有前导0。我们需要找到两个最近的靠近A的n位数(第一个比A大或与A相等,第二个严格比A小),使得它们的十进制表示是B中所有数字的某个排列。
比如说,假如A=3022并且B=1232,用B的数字我们可以获得以下的4位数字:1223, 1232, 1322, 2123, 2132, 2213, 2231, 2312, 2321, 3122, 3212和3221。最小的比A大或者和A相等的数,且用B中的数字组成的是3122,并且最大的严格比A小的数是2321。如果A=1232而且B=3022,可能的数字是2023, 2032, 2203, 2230, 2302, 2320, 3022, 3202和3220。在用B中数字组成的数中,最小的比A大或与A相等的数是2023,没有比A小的数。
对于给定的A和B,写一个程序closest找到这些“最靠近A”的数字,或者判断它们中的一个不存在。
100%的数据满足:1<=n<=60
题解
好像就是一道模拟,又看起来像一道深搜
错的原因吗?
看成了比A大的严格比A大,比A小的小于等于A
然后刚开始用的是while,不是深搜,实际上当发现不行的时候还是要向前退一步去找答案的
时间复杂度O(n2)
代码
var
c:char;
d,z:boolean;
f:array[0..65]of char;
s:string;
n,i:longint;
t:array[0..10]of longint;
procedure max(g,h:longint);
var
i:longint;
begin
if (g>n) and not z then
begin
for i:=1 to n do write(f[i]);
writeln;
z:=true;
exit;
end;
if z then exit;
for i:=0 to 9 do
if ((i>=h) or d ) and (t[i]>0) then
begin
if (i=0)and(g=1) then break;
dec(t[i]);
if i>h then d:=true;
f[g]:=chr(i+48);
max(g+1,ord(s[g+1])-48);
inc(t[i]);
end;
end;
procedure min(g,h:longint);
var
i:longint;
begin
if (g>n)and d then
begin
for i:=1 to n do write(f[i]);
z:=true;
exit;
end;
if z then exit;
for i:=9 downto 0 do
if ((i<=h) or d ) and (t[i]>0) then
begin
if (i=0)and(g=1) then break;
dec(t[i]);
if i<h then d:=true;
f[g]:=chr(i+48);
min(g+1,ord(s[g+1])-48);
inc(t[i]);
end;
end;
begin
readln(s);
n:=length(s);
for i:=1 to n do
begin
read(c);
inc(t[ord(c)-48]);
end;
max(1,ord(s[1])-48);
if not z then writeln('0');
z:=false;d:=false;
min(1,ord(s[1])-48);
if not z then writeln('0');
end.