您的位置:首页 > 其它

CQOI2012 BZOJ2669 【NOIP2016提高A组模拟8.15】Garden

2016-08-16 22:33 525 查看
//终于把这!@#¥%U!%@#^&@#()&&@%¥的题目切掉了

题目



Input



Sample Input

2

3 2

X.

..

.X

2 2

X.

..

Output



Sample Output

60

6

Data Constraint



题目大意

有一个N*M的数组,每一个位置有X和.两种,将1到n *m填入这个数组中,所有X,并且是只有X的八相邻位置都要比X这个位置的值大,求方案数。(如果有一个“.”的八相邻位置都比当前位置大,那么这种情况是不合法的)

比赛时の想法

好难啊不会(╯‵□′)╯

正解

对于40%,不难发现一组数据中X的数量最多不会超过8,那么我们考虑状压所有为X的的位置,定义rest数组为可以填数的位置(未标记)加已经填了数的位置(标记)的和(这些位置填了对后面的数没有影响,即没有后效性)。然后我们就可以状压dp了,dp的方程式是十分明显的。F[i][S]=F[i−1][S]∗(Rest[S]–i+1)+∑p∈sf[i−1,s−p]。(设f[i,s]表示正在为数字i选择对应的位置,X的状态为S)

对于100%的数据,现在的问题是可能会有一些点出现题目大意中描述的不合法的情况,这个时候我们容斥一下就可以了(把这样的”.”也当成”X”,然后在去跑状压dp,看一下程序里面就很容易懂了~)

贴代码

const md=12345678;
var
f:array[0..30,0..300]of int64;
p:array[0..300]of int64;
c:array[0..10,0..10]of longint;
s:array[0..10,0..10]of char;
g:array[0..10]of int64;
q:array[1..8,1..2]of longint=((1,1),(1,0),(1,-1),(0,1),(0,-1),(-1,1),(-1,0),(-1,-1));
i,j,k,l,n,m,t,o:longint;
ans:int64;
ch:char;
function ps(x:int64):int64;inline;
begin
if x=1 then exit(-1) else exit(1);
end;
function max(x,y:longint):longint;inline;
begin
if x>y then exit(x) else exit(y);
end;
function getans:int64;inline;
var
i,j,k,l,x,y,t1,t2:longint;
begin
l:=0;
for i:=1 to n do
for j:=1 to m do
if s[i,j]='X' then inc(l);
fillchar(p,sizeof(p),0);
for i:=0 to g[l+1]-1 do
begin
k:=0;
fillchar(c,sizeof(c),0);
for x:=1 to n do
for y:=1 to m do
begin
if s[x,y]='.' then continue;
inc(k);
if i and g[k]=0 then
begin
c[x,y]:=1;
for j:=1 to 8 do c[x+q[j,1],y+q[j,2]]:=1;
end;
end;
for x:=1 to n do
for y:=1 to m do if c[x,y]=0 then inc(p[i]);
end;
fillchar(f,sizeof(f),0);
f[0,0]:=1;
for i:=1 to n*m do
for j:=0 to g[l+1]-1 do
begin
f[i,j]:=(f[i-1,j]*max(p[j]-i+1,0)) mod md;
for k:=1 to l do
if j and g[k]>0 then
f[i,j]:=(f[i,j]+f[i-1,j-g[k]]) mod md;
end;
exit(f[I,J]);
end;
procedure dfs(x,y,z:longint);inline;
var
i,t1,t2:longint;
bz:boolean;
begin
if y=m+1 then
begin
y:=1;
inc(x);
end;
if x=n+1 then
begin
ans:=(ans+z*getans+md) mod md;
//   writeln(ans);
exit;
end;
dfs(x,y+1,z);
bz:=true;
if s[x,y]='X' then bz:=false;
if bz=true then
for i:=1 to 8 do
begin
t1:=x+q[i,1];
t2:=y+q[i,2];
if s[t1,t2]='X' then
begin
bz:=false;
break;
end;
end;
if bz=true then
begin
s[x,y]:='X';
dfs(x,y+1,ps(z));
s[x,y]:='.';
end;
end;
procedure qing;
begin
for i:=1 to n do
for j:=1 to m do s[i,j]:=' ';
end;
begin
readln(o);
g[1]:=1;
for i:=2 to 10 do g[i]:=g[i-1]*2;
for o:=1 to o do
begin
readln(n,m);
for i:=1 to n do
begin
for j:=1 to m do read(s[i,j]);
readln;
end;
ans:=0;
l:=0;
for i:=1 to n do
for j:=1 to m do
begin
if s[i,j]='X' then
begin
inc(l);
for k:=1 to 8 do
if s[i+q[k,1],j+q[k,2]]='X' then
ans:=-1;
if ans=-1 then break;
end;
end;
if l=0 then ans:=-1;
if ans=-1 then
begin
writeln(0);
qing;
continue;
end;
ans:=0;
dfs(1,1,1);
writeln(ans);
qing;
end;
end.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: