bzoj1879: [Sdoi2009]Bill的挑战(codevs2308)(luoguP2167) 状压dp

唔...懒兔子来写博客了...

点我看题

这题的话...我想了很久但是都不是可行解

刚开始想预处理任意两个串是否可以匹配然后在乱搞,后来发现完全不会写...

然后按照惯例,我会看题解认真的思考...

唔...其实看完题解貌似这题还挺容易的?

我们可以预处理一个数组 g[i,j] 表示 在这 n 个串中前 i 个字符且第 i 个字符匹配为 j (j 是一个字符) 时的一个状态。

这个状态为一个长度为n的 2进制数转为10进制。比如 111 这个状态指 1 串和2 串和 3 串都是可以匹配的。

这个数组就是这个作用。

辣它可以干什么捏。

我萌进入dp部分。

设 f[i,j] 表示 每个串前 i 个字符 状态为 j 的方案数。

初始化就是 f[0,1 << n-1]=1

答案就是 sum(f[n,j]) 这里的 j 状态要满足 二进制1 的个数为 k。

j 这个状态指 n 个串中选了哪些串。

f[i,j & g[i,x]+=f[i-1,j]

 枚举一个 x 字符,对于 ‘a’-‘z’ 这些字符都可以是第 i 位的。

然后枚举前继状态 j  辣么 对于要更新的状态就是    j & g[i,x] 

为什么是&?  因为如果能转移到的必须要满足   g[i,x] 中能匹配这个串 同时前继状态也要有。

而 & 就是只有两个都是1 的时候才为 1 ,所以 & 后就是可以转移的一个状态。

这样打完之后捏,我兴高采烈的交了上去。TLE!!!

算了一下效率,似乎是卡着的呀QAQ 

怀疑兔生的我优化了常数,以为是常数的锅。

结果还是 TLE! TLE!TLE!

然后怀疑兔生的又看了一次题解 开始思考原因

发现题解里加了优化的QAQ 但是并没有说...

所以要加一个优化咯。

这样考虑对于 f[i-1,j]=0 的情况 实际上可以不去转移,这样可以省掉很多时间。

 1 const HR=1000003;
 2 var s:string;
 3     i,j,x:longint;
 4     g:array[0..55,0..26]of longint;
 5     t,n,k:longint;
 6     f:array[0..55,0..35000]of longint;
 7     num:array[0..35000]of longint;
 8     len:longint;
 9     ans:longint;
10 function check(x:longint):longint;
11 var i,num:longint;
12 begin
13   num:=0;
14   for i:=1 to 15 do
15   if (1 << (i-1))and x>0 then inc(num);
16   exit(num);
17 end;
18 begin
19   read(t);
20   for i:=0 to (1 << 15)-1 do
21   num[i]:=check(i);
22   while t>0 do
23   begin
24     dec(t);
25     ans:=0;
26     readln(n,k);
27     for i:=1 to n do
28     begin
29       readln(s);
30       if i=1 then len:=length(s);
31       for j:=1 to len do
32         for x:=0 to 25 do
33         if ((ord(s[j])-97)=x)or(s[j]='?') then
34           g[j,x]:=g[j,x] or (1 << (i-1));
35     end;
36     f[0,(1 << n)-1]:=1;
37     for i:=1 to len do
38     begin
39       for j:=0 to (1 << n)-1 do
40       if f[i-1,j]<>0 then
41       begin
42         for x:=0 to 25 do
43         begin
44           inc(f[i,(g[i,x] and j)],f[i-1,j]);
45           if f[i,(g[i,x] and j)]>=HR then
46             f[i,(g[i,x] and j)]:=f[i,(g[i,x] and j)] mod HR;
47         end;
48         f[i-1,j]:=0;
49       end;
50       if i=len then
51       begin
52         for j:=0 to (1 << n)-1 do
53         begin
54           if num[j]=k then
55           begin
56             inc(ans,f[len,j]);
57             if ans>=HR then ans:=ans mod HR;
58           end;
59           f[i,j]:=0;
60         end;
61       end;
62     end;
63     for i:=1 to len do
64     for x:=0 to 25 do
65     g[i,x]:=0;
66     writeln(ans);
67   end;
68 end.
bzoj1879

代码巨丑...懒兔子懒得弄好看点了QAQ

 

posted @ 2017-09-03 18:26  Bunnycxk  阅读(267)  评论(0编辑  收藏  举报