题目: | 虫食算 | |
来源: | Noip2004T4 | |
题目大意: | 3个有N个字母的字符串,求使其能构成加法竖式性质的代数,并按字母顺序输出他 们 | |
数据范围: | N <= 26 | |
样例: | 5 ABCED BDACE EBBAA | 1 0 3 4 2 |
做题思路: | 搜索是正解,从个位的每个数开始搜,而且每一步都要判断等式和这一列是否矛盾, 代码好长,当初就over在优化那里了,现在还是copy的牛代码。。仅供参考 | |
知识点: | 搜索 |
var
s:array[1..3] of string;
a:array['A'..'Z'] of longint;
b:array['A'..'Z'] of boolean;
c:array[-28..50] of char;
h:array[0..27] of char;
n:longint;
i,j:longint;
tot:longint;
ch:char;
function print:boolean;
var
i:longint;
ans:longint;
begin
ans:=0;
fori:=n downto 1 do{<当枚举完后在进行最后一步的整体判断,如若满足则输出>}
if(a[s[1][i]]+a[s[2][i]]+ans) mod n = a[s[3][i]] thenans:=(a[s[1][i]]+a[s[2][i]]+ans) div n
elseexit(false);
write(a['A']);
forch:='B' to chr(ord('A')+n-1) do write(' ',a[ch]);
writeln;
exit(true);
end;
function cheak:boolean;{<如果某列已经枚举了两个则计算出第三个,如果已经有三个则判断是否矛盾,如果只枚举了一个则继续,如果不矛盾则继续>}
var
i:longint;
bb:boolean;
begin
fori:=n downto 1 do
begin
if(b[s[1][i]]) and (b[s[2][i]]) and (b[s[3][i]]) then
if((a[s[1][i]]+a[s[2][i]]+1) mod n = a[s[3][i]]) or ((a[s[1][i]]+a[s[2][i]]) modn = a[s[3][i]]) then
begin
continue;
end
else exit(false);
if(b[s[1][i]]) and (b[s[2][i]]) then
if(c[(a[s[1][i]]+a[s[2][i]]) mod n] = '*') or ((c[(a[s[1][i]]+a[s[2][i]]+1) modn] = '*')) then
begin
continue;
end
else exit(false);
if(b[s[1][i]]) and (b[s[3][i]]) then
if(c[a[s[3][i]]-a[s[1][i]]] = '*') or (c[a[s[3][i]]-a[s[1][i]]-1] = '*') or(c[a[s[3][i]]+n-a[s[1][i]]] = '*') or (c[a[s[3][i]]-a[s[1][i]]-1+n] = '*') then
begin
continue;
end
else exit(false);
if(b[s[2][i]]) and (b[s[3][i]]) then
if(c[a[s[3][i]]-a[s[2][i]]] = '*') or (c[a[s[3][i]]-a[s[2][i]]-1] = '*') or(c[a[s[3][i]]+n-a[s[2][i]]] = '*') or (c[a[s[3][i]]-a[s[2][i]]-1+n] = '*') then
begin
continue;
end
else exit(false);
end;
exit(true);
end;
procedure dfs(l:longint);
var
i:longint;
begin
if l> n then
begin
ifprint then
begin
halt;
end
elseexit;
end;
fori:=n-1 downto 0 do
ifc[i] = '*' then{<这个不是乘号,是该字母还没枚举的标志>}
begin
b[h[l]]:=true;
a[h[l]]:=i;
c[i]:=h[l];
ifcheak then dfs(l+1);
b[h[l]]:=false;
a[h[l]]:=-1;
c[i]:='*';
end;
end;
begin
for ch:='A'to 'Z' do b[ch]:=false;
readln(n);
readln(s[1]);
readln(s[2]);
readln(s[3]);
tot:=0;
fori:=n downto 1 do {<字母枚举顺序是字符串倒着每列自上向下>}
forj:=1 to 3 do
ifnot b[s[j][i]] then
begin
inc(tot);
h[tot]:=s[j][i];
b[s[j][i]]:=true;
end;
fori:=-28 to 50 do c[i]:='*';
for ch:='A'to 'Z' do
begin
b[ch]:=false;
a[ch]:=-1;
end;
dfs(1);
end.