码迷,mamicode.com
首页 > 其他好文 > 详细

hdu 5677 ztr loves substring(manacher,背包问题)

时间:2016-05-01 19:02:42      阅读:236      评论:0      收藏:0      [点我收藏+]

标签:

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 typedef long long ll;
  4 
  5 /**
  6 
  7 
  8     manacher 处理出回文串长度
  9         p[i]:半径
 10 
 11         if(s[i] == ‘#‘ && p[i] == 1) continue;
 12         else{
 13             int tmp = p[i] / 2;
 14             if(s[i] == ‘#‘) for(int i = 2 ; i <= tmp ; i += 2) cnt[i]++;
 15             else    for(int i = 1 ; i <= tmp ; i += 2) cnt[i]++;
 16         }
 17 
 18 问题就变成 : 有 n 种 大小不同的数字 a[i] , 每种 mi个,是否可以选出k个和为l
 19 背包问题:
 20         a[i] : 第i个数的值为 a[i];
 21         m[i] : 第i个数的个数为 m[i];
 22 
 23         memset(dp,0,sizeof(dp));
 24         dp[0][0] = 1;
 25         for(int i = 0 ; i < t ; i ++){
 26             for(int j = l ; j >= a[i] ; j --){
 27                 for(int jj = m[i] ; jj <= k ; jj ++){
 28                     dp[jj][j] |= dp[jj-m[i]][j-a[i]];
 29                 }
 30             }
 31         }
 32 
 33 */
 34 
 35 
 36 const int MAX=100+10;
 37 int p[MAX*2];
 38 int cnt[MAX*2];
 39 int a[MAX*2],m[MAX*2];
 40 int dp[110][110];
 41 int n,k,l,t;
 42 void manacher(char *s){
 43     int len=strlen(s),id=0,maxlen=0;
 44     for(int i=len;i>=0;--i){//插入‘#‘
 45         s[2*i+2]=s[i];
 46         s[2*i+1]=#;
 47     }
 48     s[0]=*;
 49     for(int i=2;i<2*len+1;++i){
 50         if(p[id]+id>i) p[i]=min(p[2*id-i],p[id]+id-i);
 51         else p[i]=1;
 52         while(s[i-p[i]] == s[i+p[i]])  ++p[i];
 53         if(id+p[id]<i+p[i])    id=i;        //记录最长延伸点
 54 //      if(maxlen<p[i])        maxlen=p[i];
 55 
 56         if(s[i] == # && p[i] == 1) continue;
 57         else{
 58   //          cout << i << "        " << p[i] << endl;
 59             int tmp = p[i] ;
 60             if(s[i] == #) for(int j = 2 ; j <= p[i]-1 ; j += 2) cnt[j]++;
 61             else    for(int j = 1 ; j <= p[i]-1 ; j += 2) cnt[j]++;
 62         }
 63     }
 64 }
 65 
 66 int main(){
 67 
 68     int T;
 69     scanf("%d",&T);
 70     char str[110*2];
 71     while(T--){
 72         memset(a,0,sizeof(a));
 73         memset(m,0,sizeof(m));
 74         memset(cnt,0,sizeof(cnt));
 75         memset(dp,0,sizeof(dp));
 76 
 77         scanf("%d%d%d",&n,&k,&l);
 78         for(int i = 0 ; i < n ; i ++){
 79             scanf("%s",str);
 80             manacher(str);
 81         }
 82 /**
 83 例如 值为10的个数为cnt = 7;
 84 可以拆成值为 10 的个数为 1,2,4;  选六个只需选择其中的2,4
 85 */
 86         t = 0;
 87         for(int i = 0 ; i <= 100 ; i ++){
 88             int tmp = 1;
 89             while(cnt[i] >= tmp){
 90                 a[t] = tmp*i , m[t++] = tmp;
 91                 cnt[i] -= tmp;
 92                 tmp *= 2;
 93             }
 94             if(cnt[i]){
 95                 a[t] = cnt[i]*i , m[t++] = cnt[i];
 96             }
 97         }
 98 
 99 /**
100 a[i] : 第i个数的值为 a[i];
101 m[i] : 第i个数的个数为 m[i];
102 */
103         memset(dp,0,sizeof(dp));
104         dp[0][0] = 1;
105         for(int i = 0 ; i < t ; i ++){
106             for(int j = l ; j >= a[i] ; j --){
107                 for(int jj = m[i] ; jj <= k ; jj ++){
108                     dp[jj][j] |= dp[jj-m[i]][j-a[i]];
109                 }
110             }
111         }
112 
113         if(dp[k][l]) printf("True\n");
114         else printf("False\n");
115     }
116 
117     return 0;
118 }

 

hdu 5677 ztr loves substring(manacher,背包问题)

标签:

原文地址:http://www.cnblogs.com/zstu-jack/p/5450861.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!