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

  • 相关阅读:
    C#根据html生成PDF
    Oracle 存储过程异常处理
    Oracle事务之一:锁和隔离
    跨域解决方案一:使用CORS实现跨域
    AJAX POST&跨域 解决方案
    使用 jQuery Deferred 和 Promise 创建响应式应用程序
    jQuery:多个AJAX/JSON请求对应单个回调并行加载
    解决td标签上的position:relative属性在各浏览器中的兼容性问题
    盘点8种CSS实现垂直居中水平居中的绝对定位居中技术
    JQuery-UI Dialog下使用服务器端按钮失效
  • 原文地址:https://www.cnblogs.com/Konjakmoyu/p/5241761.html
Copyright © 2011-2022 走看看