zoukankan      html  css  js  c++  java
  • UVA1204 Fun Game

    Fun Game

     

    https://odzkskevi.qnssl.com/8d698323a1e07d605cdeea708ee8a01d?v=1508703139

    【题解】

    不难发现如果一个串的原串或反转串是另一个串的子串,那么这个串是没有用的

    我们把他剔除出去

    如果此时只有一个串,暴力枚举解检查即可(网上很多写法是KMP。。不是很明白,没仔细看他们代码

    多个串则状压DP

    dp[s][i][0/1]表示s串已经选了,最后一个串是i,i是正着/倒着的,最大重叠字母数

    刷表法转移即可

    如何处理圈?我们强行在第一个串的地方断开,按照第一个串的正着的方向为圈的传递方向即可,

    最后的时候枚举最后一个串跟第一个串交一下算答案

      1 #include <iostream>
      2 #include <algorithm>
      3 #include <cstdio>
      4 #include <cstdlib>
      5 #include <cstring>
      6 #include <vector> 
      7 #define min(a, b) ((a) < (b) ? (a) : (b))
      8 #define max(a, b) ((a) > (b) ? (a) : (b))
      9 
     10 inline void swap(int &a, int  &b)
     11 {
     12     long long tmp = a;a = b;b = tmp;
     13 }
     14 
     15 inline void read(int& x)
     16 {
     17     x = 0;char ch = getchar(), c = ch;
     18     while(ch < '0' || ch > '9')c = ch, ch = getchar();
     19     while(ch <= '9' && ch >= '0')x = x * 10 + ch - '0', ch = getchar();
     20 }
     21 
     22 const int INF = 0x3f3f3f3f;
     23 const int MAXN = 20;
     24 const int MAXNUM = 1000;
     25 
     26 int dp[(1 << MAXN) + 10][MAXN + 5][2], die[MAXN][2][MAXN][2], n, ma, sum, len[MAXN], cnt[MAXN], tot, b[MAXN];
     27 char s[MAXN][MAXNUM];
     28 
     29 inline void init()
     30 {
     31     memset(dp, 0, sizeof(dp));
     32     memset(die, 0, sizeof(die));
     33     tot = 0;
     34     sum = 0;
     35     memset(b, 0, sizeof(b));
     36     memset(len, 0, sizeof(len));
     37     memset(cnt, 0, sizeof(cnt));
     38     //check j是否包含在i中 
     39     for(register int i = 1;i <= n;++i) 
     40     {
     41         scanf("%s", s[i] + 1);
     42         len[i] = strlen(s[i] + 1);
     43     }
     44     for(register int i = 1;i <= n;++ i)
     45         for(register int j = 1;j <= n;++ j)
     46         {
     47             if(i == j || b[i] || b[j] || len[j] > len[i])continue;
     48             //正着配 
     49             for(register int a = 1;a <= len[i] - len[j] + 1;++ a)
     50             {
     51                 int tmp1 = a;
     52                 while(s[i][tmp1] == s[j][tmp1 - a + 1] && tmp1 - a + 1 <= len[j]) ++ tmp1;
     53                 if(tmp1 - a + 1 > len[j]) b[j] = 1;
     54             }
     55             //倒着配
     56             for(register int a = len[i];a >= len[j];-- a)
     57             {
     58                 int tmp1 = a, p = 1;
     59                 while(s[i][tmp1] == s[j][p] && p <= len[j]) -- tmp1, ++ p;
     60                 if(p > len[j]) b[j] = 1;
     61             }
     62         }
     63     for(register int i = 1;i <= n;++ i)
     64         if(!b[i])
     65             cnt[++ tot] = i, sum += len[i];
     66     //j跟在i后面重叠部分大小 
     67     for(register int p = 1;p <= tot;++ p)
     68         for(register int q = 1;q <= tot;++ q)
     69         {
     70             int i = cnt[p], j = cnt[q];
     71             if(i == j)continue;
     72             //0 0
     73             for(register int a = 1;a <= len[i];++ a)
     74             {
     75                 int b = 1, tmp = a;
     76                 while(s[i][tmp] == s[j][b] && tmp <= len[i] && b <= len[j])++ tmp, ++ b;
     77                 if(tmp > len[i]) 
     78                 {
     79                     die[p][0][q][0] = len[i] - a + 1;
     80                     break;
     81                 }
     82             }
     83             //0 1
     84             for(register int a = 1;a <= len[i];++ a)
     85             {
     86                 int b = len[j], tmp = a;
     87                 while(s[i][tmp] == s[j][b] && tmp <= len[i] && b >= 1)++ tmp, -- b;
     88                 if(tmp > len[i]) 
     89                 {
     90                     die[p][0][q][1] = len[i] - a + 1;
     91                     break;
     92                 }
     93             }
     94             //1 0
     95             for(register int a = len[i];a >= 1;-- a)
     96             {
     97                 int b = 1, tmp = a;
     98                 while(s[i][tmp] == s[j][b] && tmp >= 1 && b <= len[j])-- tmp, ++ b;
     99                 if(tmp < 1) 
    100                 {
    101                     die[p][1][q][0] = a;
    102                     break;
    103                 }
    104             }
    105             //1 1
    106             for(register int a = len[i];a >= 1;-- a)
    107             {
    108                 int b = len[j], tmp = a;
    109                 while(s[i][tmp] == s[j][b] && tmp >= 1 && b >= 1)-- tmp, -- b;
    110                 if(tmp < 1) 
    111                 {
    112                     die[p][1][q][1] = a;
    113                     break;
    114                 }
    115             }
    116         }
    117         ma = 1 << tot;
    118 }
    119 
    120 int main()
    121 {
    122     while(scanf("%d", &n) != EOF && n)
    123     {
    124         init();
    125         int flag = 0;
    126         if(tot == 1)
    127         {
    128             int x = cnt[tot];
    129             for(register int i = 1;i <= len[x];++ i)
    130             {
    131                 for(register int j = 1;j <= len[x];++ j)
    132                 {
    133                     if(j + i - 1 > len[x]) break;
    134                     int p1 = 1, p2 = j, rank = 0;
    135                     while(s[x][p1] == s[x][p2] && rank < len[x])
    136                     {
    137                         ++ p1, ++ p2, ++ rank;
    138                         if(p1 > len[x]) p1 = 1;
    139                         if(p2 > j + i - 1) p2 = 1;
    140                     }
    141                     if(rank >= len[x])
    142                     {
    143                         printf("%d
    ", max(2, i));
    144                         flag = 1;
    145                         break;
    146                     }
    147                 }
    148                 if(flag) break;
    149             }
    150             if(flag) continue;
    151         }
    152         //dp[S][i][0/1]表示以1号字符串为头,已经选了S,最后一个是i的正/反状态的最大折叠数 
    153         //dp[S | k][k][p] = max(dp[S | k][k][p], dp[S][i][p'] + die[i][p'][k][p])
    154          for(register int S = 0;S < ma;++ S)
    155             for(register int i = 1;i <= tot;++ i)/*分别用dp[S][i][0]和dp[S][i][1]去更新*/
    156             {
    157                 if(!(S & 1))continue;
    158                 if(!(S & (1 << (i - 1)))) continue;
    159                 for(register int k = 1;k <= tot;++ k)
    160                 {
    161                     if(S & (1 << (k - 1))) continue;
    162                     if(S == 1)
    163                     {
    164                         dp[S | (1 << (k - 1))][k][0] = max(dp[S | (1 << (k - 1))][k][0], dp[S][i][0] + die[i][0][k][0]);
    165                         dp[S | (1 << (k - 1))][k][1] = max(dp[S | (1 << (k - 1))][k][1], dp[S][i][0] + die[i][0][k][1]);                        
    166                     }
    167                     else
    168                     {
    169                         dp[S | (1 << (k - 1))][k][0] = max(dp[S | (1 << (k - 1))][k][0], max(dp[S][i][0] + die[i][0][k][0], dp[S][i][1] + die[i][1][k][0]));
    170                         dp[S | (1 << (k - 1))][k][1] = max(dp[S | (1 << (k - 1))][k][1], max(dp[S][i][0] + die[i][0][k][1], dp[S][i][1] + die[i][1][k][1]));
    171                     }
    172                 }
    173             }
    174         int ans = 0;
    175         for(register int i = 1;i <= tot;++i)
    176             ans = max(ans, max(dp[ma - 1][i][0] + die[i][0][1][0], dp[ma - 1][i][1] + die[i][1][1][0]));
    177         printf("%d
    ", max(2, sum - ans));
    178     }
    179     return 0;
    180 }
    UVA1204
  • 相关阅读:
    冒泡排序
    Bootstrap fileinput v1.0(ssm版)
    Bootstrap table后端分页(ssm版)
    Bootstrap table前端分页(ssm版)
    北京鱼乐贝贝面试题
    通过前端控制器源码分析springmvc的执行过程
    java Pattern(正则)类
    ssm所需要的pom(jre8、tomcat8、spring4)
    Java 流(Stream)、文件(File)和IO
    idea构建一个简单的maven_web项目
  • 原文地址:https://www.cnblogs.com/huibixiaoxing/p/7728683.html
Copyright © 2011-2022 走看看