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
对于100%的数据,现在的问题是可能会有一些点出现题目大意中描述的不合法的情况,这个时候我们容斥一下就可以了(把这样的”.”也当成”X”,然后在去跑状压dp,看一下程序里面就很容易懂了~)
题目
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.
相关文章推荐
- PHP 验证码 浅析
- hdu 5852 Intersection is not allowed! (2016多校第九场1009)组合
- PHP 验证码 浅析
- dubbo 试用全过程
- Android 自定义Adapter
- PreferenceActivity简单用法
- sublime Text3安装,删除,更新插件
- 基于Flume+Kafka+Spark-Streaming的实时流式处理完整流程
- JAVA基础 引用类型变量和基本类型变量
- Unreal Framework & Network
- hdu 5840 This world need more Zhu (2016CCPC 网络赛1009) 分块+线段树
- Macbook之设置Finder显示文件完整路径
- 每天学点知识
- Dot 与 GraphViz 经验总结
- idea创建Spark Maven项目
- [Android 数据存储] SDcard/Android/data/ 这个目录是干什么的?
- Mirantis OpenStack 9.0 在 VirtualBox上的部署安装
- 12.hibernate命名查询
- Android中的Service
- 学习load acquire 和store release