密码锁
问题描述
小 A 退了课程和社团之后,感到了一身轻松。正逢秋高气爽,他约上了妹子小 B 到郊外游玩。一路上,他们愉快地讨论着基于连通性的状态压缩动态规划、线段跳表、树链剖分等人民群众喜闻乐见的问题,愉快地穿梭于树、精美的图和仙人掌之中。这时他们的目光被一个数字密码锁吸引了,这个密码锁只有 0 和 1 两个按键和一个长度为K 的显示屏。边上还很友好地附着一张说明书,告诉他们这一密码锁是滚动的,即当输入第K+1 位数字时,最先输入的数字将会从屏幕上删去,新输入的数字将会成为屏幕上的第 K 位数字。当这个长度为 K 的显示屏上呈现出正确的 K 位密码时,他们将会获得神秘的宝藏;但是如果他们尝试了两个相同的密码,这个密码锁将会爆炸。
小 A 已经跃跃欲试了,想在小 B 面前出出风头。他希望能够获得一个输入序列,使得试过的密码数最多,同时输入的过程中不会爆炸。为了显得更优雅,小 A 希望这一序列的字典序最小,其中 0 小于 1。你知道这一序列是什么吗?
输入
输入文件名为 lock.in。
一个整数 K。
输出
输出文件名为 lock.out。
一个整数 M 和一个 M 位二进制串,由一个空格分隔。这二进制串是小 A 输入的最小字典序的二进制串。
Sample Input
3
Sample Output
10 0001011100
样例说明
尝试的 8 个 3 位密码分别是 000、001、010、101、011、111、110 和 100。注意前后是相邻的。长度为 3 的二进制串总共只有 8 种,所以尝试了 8 种一定是可能的最大值。
数据范围
对于 100%的数据,2≤K≤11。
题解
反正怎么看我都想打表 - 最后还是打了
不过我们对搜索过程优化一下,还是可以压缩到1S以内的。
由题目我们可以看出来,一旦搜索到的当前方位出现了重复的数字,就应该立即退出该层循环,返回上一层。由于该题要求字典序最下,我们优先搜索‘0’,而搜索过程中的判重,可以将二进制转换成十进制判重即可。并且从题目中,我们可以推出所求字典长度为(2^(k) ) +k-1。
附上Pascal代码:
program baoli;
var a,b:array[0..100000] of integer;
f:Array[0..5000] of boolean;
i,j,k,g,n,max,min:longint;
function power(a,b:longint):longint;//power函数
var ans,i,j:longint;
begin
ans:=1;
if (b=0) and (a >0) then exit(1);
for i:=1 to b do
ans:=ans*a;
exit(ans);
end;
function change(l,r:longint):longint; //转成二进制
var i,j,ans:longint;
begin
ans:=0;
for i:=l to r do
begin
ans:=ans+a[i] * power(2,i-l);
end;
exit(ans);
end;
procedure search(k:longint);//dfs
var i,j,tmp,cnt:longint;
flag:boolean;
begin
if k<=g then
for j:=0 to 1 do
begin
a[k]:=j;
flag:=true;
fillchar(f,sizeof(f),true);
for i:=1 to k-n+1 do
begin
tmp:=change(i,i+n-1);
if f[tmp] then
begin
inc(cnt);
f[tmp]:=false;
end
else
begin
flag:=false;//flag标记当前是否已经出现重复数字,有则为false
break;
end;
end;
if flag then//如果flag为true,即无重复数字再继续搜索
search(k+1);
a[k]:=0;
end
else
begin
fillchar(f,sizeof(f),true);
cnt:=0;
for i:=1 to g-n+1 do
begin
tmp:=change(i,i+n-1);
if f[tmp] then
begin
inc(cnt);
f[tmp]:=false;
end
else
begin
exit;
end;
end;
if cnt>max then begin max:=cnt;b:=a;end;
if cnt = g+1-n then
begin
for i:=1 to g do
write(a[i]);
close(output);
halt;
end;
end;
end;
begin
assign(input,'lock.in');reset(input);
assign(output,'lock.out');rewrite(output);
read(n);
max:=-maxlongint;
fillchar(a,sizeof(a),0);
g:=power(2,n) + n -1;
write(g,' ');
search(1);
for i:=1 to g do
write(b[i]);
close(output);
end.
不过这题还可以利用欧拉路的思想来求解,压栈出解