• 【UVA1633】禁止的回文串(状压DP)


    题意:

      输入正整数n和k(1<=n<=400,1<=k<=10),求长度为n的01串中有多少个不含长度至少为k的回文连续子串。例如,n=k=3时只有4个串满足条件:001,011,100,110。

    分析:

      做这题的时候走了很多弯路,自以为想到了一个不用表示状态的dp,然而在保证不回文的时候就发现了很多问题。其实本题k的规模很小,所以应该要想到状压的。一个串中只要保证不含长度为k也不含长度为k+1的回文串,那么就不会出现大于k的回文串,所以我们构造的时候只要保证前面两个条件符合即可。

      状压记录后k的字符串,填新字符时保证不会构造出长度为k或k+1的回文串即可。

    代码如下:

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstdlib>
     4 #include<cstring>
     5 #include<iostream>
     6 using namespace std;
     7 #define Maxn 410
     8 #define Maxd 3010
     9 #define Mod  1000000007
    10 
    11 int f[Maxn][Maxd];
    12 
    13 bool check(int x,int kl)
    14 {
    15     int sl=1<<kl-1,sr=1;
    16     for(int i=1;i<=kl/2;i++)
    17     {
    18         int l=x&sl,r=x&sr;
    19         if((l&&(!r))||(!l&&r)) return 0;
    20         sr<<=1;sl>>=1;
    21     }
    22     return 1;
    23 }
    24 
    25 int main()
    26 {
    27     int T;
    28     scanf("%d",&T);
    29     while(T--)
    30     {
    31         int n,k;
    32         scanf("%d%d",&n,&k);
    33         if(k==1) {printf("0
    ");continue;}
    34         memset(f,0,sizeof(f));
    35         f[0][0]=1;
    36         int ans=0;
    37         for(int i=1;i<=n;i++)
    38         {
    39             for(int j=0;j<=(1<<k+1)-1;j++) if(f[i-1][j]!=0)
    40             {
    41                 bool p0=1,p1=1;
    42                 if(i>k&&check(j&((1<<k-1)-1),k-1))
    43                 {
    44                     if(j&(1<<k-1)) p1=0;
    45                     else p0=0;
    46                 }
    47                 if(i>=k&&check(j&((1<<k-2)-1),k-2))
    48                 {
    49                     if(j&(1<<k-2)) p1=0;
    50                     else p0=0;
    51                 }
    52                 int now=(j&((1<<k)-1))*2;
    53                 if(p0) f[i][now]=(f[i][now]+f[i-1][j])%Mod;
    54                 now=((j&((1<<k)-1))*2)+1;
    55                 if(p1) f[i][now]=(f[i][now]+f[i-1][j])%Mod;
    56             }
    57         }
    58         for(int i=0;i<=(1<<k+1)-1;i++)
    59             ans=(ans+f[n][i])%Mod;
    60         printf("%d
    ",ans);
    61     }
    62     return 0;
    63 }
    uva1633

    这题没有特判k=1的情况导致WA了很久,可能是我的代码风格太渣的问题TAT。

    2016-03-04 13:25:02

  • 相关阅读:
    贪心算法
    分治法
    递归法
    查找二 树与图的搜索
    (转载)查找三 哈希表的查找
    (转载)查找一 线性表的查找
    4.写出完整版的strcpy函数
    3.strcpy使用注意(3)
    2.strcpy使用注意(2)
    1.strcpy使用注意
  • 原文地址:https://www.cnblogs.com/Konjakmoyu/p/5241761.html
Copyright © 2020-2023  润新知