zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    [Scala] akka actor编程(一)
    随便说说
    [Java] Java执行Shell命令
    [Scala] Scala基础知识
    [Linux] 账户管理命令(二)
    [Linux] 账户管理命令(一)
    [Kerberos] Java client访问kerberos-secured cluster
    沟通与影响技术培训
    Python
    ML 基础知识
  • 原文地址:https://www.cnblogs.com/Bunnycxk/p/7470413.html
Copyright © 2011-2022 走看看