P2198 [JZOJ/中山市市选] 简单数迷
给你一个矩阵,有一些格子有数字,有一些没有。没有数字的格子的个数 \(\leq 4^2\)。让你用 \(1\)~\(9\) 填满所有没有数字的格子,使得每一行每一列等于给出的它数字。
如:
首先我们知道如果直接暴力 \(9^{4^2}\) 的,肯定爆炸。
不过我们有自己的优化方式。
首先我们记录 \(rest_{i,1/2}\) 代表某一个行或者列还剩几个数字没有填,\(1\) 是行,\(2\) 是列。以及我们可以设一个 \(sum_{i,1/2}\) 代表某一行或列的现在的总和。其次,我们把所有空着的格子取出来,然后用队列存起来,就不用一个一个遍历。我们每一次 for i:=1 to 9 do
的时候设一个 \(front\) 和 \(border\) 代表从几遍历到几,一开始 brder:=min(min(9,condition[x,1]),condition[y,2]);
(\(condition\) 为限制),然后 if rest[x,1]=1 then border:=min(border,condition[x,1]-sum[x,1]);
if rest[y,2]=1 then border:=min(border,condition[y,2]-sum[y,2]);
。\(front\) 的修改也差不多,if (rest[x,1]=1)or(rest[y,2]=1) then front:=border;
。
数据太水,细节较多,压路机碾过。
Uses math;
Const
total=11;
var
sum,rest,condition:array[-1..total,1..2] of longint;
bucket:array[-1..total,-1..total,1..2] of longint;
ans,matrix:array[-1..total,-1..total] of longint;
queue:array[-1..121,-1..2] of longint;
i,j,n,m,way,tail,test:longint;
bz,fuck:boolean;
procedure Dfs(now:longint);
var i,k,j,x,y,front,border:longint;
begin
if fuck then exit;
if now>tail then
begin
bz:=False;
for i:=1 to n do if condition[i,1]<>sum[i,1] then begin bz:=True; break; end; if bz then exit;
for i:=1 to m do if condition[i,2]<>sum[i,2] then begin bz:=True; break; end; if bz then exit;
inc(way); if way=2 then begin writeln('Not unique.'); fuck:=True; exit; end;
ans:=matrix; exit;
end;
x:=queue[now,1]; y:=queue[now,2]; border:=min(min(9,condition[x,1]),condition[y,2]);
if rest[x,1]=1 then border:=min(border,condition[x,1]-sum[x,1]);
if rest[y,2]=1 then border:=min(border,condition[y,2]-sum[y,2]);
if border<=0 then exit; front:=1;
if (rest[x,1]=1)or(rest[y,2]=1) then front:=border;
for i:=border downto front do
begin
if (bucket[i,x,1]>0)or(bucket[i,y,2]>0) then continue;
dec(rest[x,1]); dec(rest[y,2]); inc(sum[x,1],i); inc(sum[y,2],i);
inc(bucket[i,x,1]); inc(bucket[i,y,2]);
matrix[x,y]:=i; Dfs(now+1); matrix[x,y]:=0;
dec(bucket[i,x,1]); dec(bucket[i,y,2]);
inc(rest[x,1]); inc(rest[y,2]); dec(sum[x,1],i); dec(sum[y,2],i);
end;
end;
procedure Work;
begin
fillchar(condition,sizeof(condition),0);
fillchar(bucket,sizeof(bucket),0);
fillchar(matrix,sizeof(matrix),0);
fillchar(queue,sizeof(queue),0);
fillchar(rest,sizeof(rest),0);
fillchar(sum,sizeof(sum),0);
fillchar(ans,sizeof(ans),0);
read(n,m); tail:=0; fuck:=False;
for i:=1 to n do read(condition[i,1]);
for i:=1 to m do read(condition[i,2]);
for i:=1 to n do inc(rest[i,1],m);
for i:=1 to m do inc(rest[i,2],n);
for i:=1 to n do for j:=1 to m do
begin
read(matrix[i,j]);
if matrix[i,j]=0 then begin inc(tail); queue[tail,1]:=i; queue[tail,2]:=j; end;
if matrix[i,j]>0 then
begin
dec(rest[i,1]); dec(rest[j,2]);
inc(bucket[matrix[i,j],i,1]); inc(bucket[matrix[i,j],j,2]);
end;
end;
for i:=1 to n do for j:=1 to m do inc(sum[i,1],matrix[i,j]);
for i:=1 to m do for j:=1 to n do inc(sum[i,2],matrix[j,i]);
way:=0; Dfs(1); if fuck then exit;
if way=0 then begin writeln('No answer.'); exit; end;
for i:=1 to n do begin for j:=1 to m do write(ans[i,j],' '); writeln; end;
end;
begin
assign(input,'kakuro.in');reset(input);
assign(output,'kakuro.out');rewrite(output);
read(test);
while test>0 do begin Work; dec(test); end;
close(input); close(output);
end.
完结撒花!✿✿ヽ(゚▽゚)ノ✿