Poi 2004 pin
题意:pin码是一个十六进制的有4个元素的数组。现在要你猜pin码,对于一个数组a[i],表示i通过转换后是a[i],现在你可以询问b,a,表示pin码经过a转换是否是b数组。询问次数不超过30次。
首先的想法是必需一个个考虑。先求出pin中有哪些数字,但是这个数字可能出现多次。这样的枚举量是受不了的。所以转化为哪些没出现过,也就是哪些改了无影响。16次。
确定了后,考虑只有1个数字只填在一个位置的枚举量较小,称其为匹配。
S2:根据可能数字集大小K别处理。
K={a} Ans=aaaa。
K={a,b,c,d} 询问类似((0,1,1,1),(0,1,1,1))以确定某个位置是不是某个数字。
K={a,b,c} 枚举,若发现某数字x无法匹配到某位置,那么先匹配另外两个,则剩下的两个位置均为x。
K={a,b} 两种情况:abbb与aabb。若某次匹配成功,则剩下的都是另一个数字,否则枚举C(4,2)来确定a即可。
需要次数最多的为aabb,2*4+C(4,2)=14次。
完美解决。
program xqz; uses hsm; var i,j,k,m,n,v:longint; a:array[1..16] of longint; ans,b,c:array[1..4] of longint; z:array[1..4] of boolean; ok:boolean; function check(i,j:longint):boolean; begin if i<>0 then b[i]:=1; a[j]:=1; check:=sprawdz(b,a); if i<>0 then b[i]:=0; a[j]:=0; end; procedure deal(v:longint); var i:longint; begin for i:=1 to 4 do if ans[i]=0 then ans[i]:=v; end; begin for i:=1 to 16 do if not check(0,i) then begin inc(n); c[n]:=i; end; case n of 1:for i:=1 to 4 do ans[i]:=c[n]; 4:for i:=1 to 4 do for j:=1 to 4 do if not z[j] and check(j,c[i]) then begin z[j]:=true; ans[j]:=c[i]; break; end; 3: begin for i:=1 to 3 do begin ok:=false; for j:=1 to 4 do if not z[j] and check(j,c[i]) then begin z[j]:=true; ans[j]:=c[i]; ok:=true; break; end; if not ok then v:=c[i]; end; deal(v); end; 2: begin for i:=1 to 2 do begin for j:=1 to 4 do if check(j,c[i]) then begin ans[j]:=c[i]; ok:=true; break; end; if ok then break; end; if ok then deal(c[1] xor c[2] xor c[i]) else begin a[c[1]]:=1; for i:=1 to 4 do if not ok then for j:=i+1 to 4 do begin b[i]:=1; b[j]:=1; if sprawdz(b,a) then begin ok:=true; ans[i]:=c[1]; ans[j]:=c[1]; break; end; b[i]:=0; b[j]:=0; end; deal(c[2]); end; end; end; for i:=1 to 4 do ans[i]:=(ans[i]-1) mod 10; wynik(ans); end.