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

  • 相关阅读:
    ZOJ 2158 Truck History
    Knight Moves (zoj 1091 poj2243)BFS
    poj 1270 Following Orders
    poj 2935 Basic Wall Maze (BFS)
    Holedox Moving (zoj 1361 poj 1324)bfs
    ZOJ 1083 Frame Stacking
    zoj 2193 Window Pains
    hdu1412{A} + {B}
    hdu2031进制转换
    openjudge最长单词
  • 原文地址:https://www.cnblogs.com/Konjakmoyu/p/5241761.html
Copyright © 2011-2022 走看看