• HDU 4628 Pieces(DP + 状态压缩)


    Pieces

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4628

    题目大意:给定一个字符串s,如果子序列中有回文,可以一步删除掉它,求把整个序列删除所需要的最少步数。比如: axbyczbea 可以一次删除掉 abcba 得到 xyze

    Sample Input
    2
    aa
    abb
     
    Sample Output
    1
    2
    分析:这道题目刚出来时居然有超过一半的人AC,是我太弱了吗?
      到底不会,先贴出标程,再慢慢消化好了
      

      集合上的动态规划。。。和点集配对很像,这里我先求出所有的回文串,然后dp。

      设d[S]表示将集合S中的字母删除需要多少步,结果就是d[(1<<n)-1];

      枚举所有的S,枚举所有S的子集sub;

      状态转移方程:d[S] = min(d[S], d[S^sub)] + 1](如果sub是回文串~这样才算能减一步呀);

     
    代码如下:
     1 # include<cstdio>
     2 # include<cstring>
     3 # include<algorithm>
     4 
     5 using namespace std;
     6 
     7 const int maxn = 16 + 1;
     8 const int INF = 0xffffff;
     9 char s[maxn];
    10 bool ispal[1<<maxn];    //ispal[i]表示状态i是否是回文,2进制时1表示选择这个字符,0表示不选择这个字符
    11 int d[1<<maxn];        //d[S]表示将集合S中的字母删除需要多少步,结果就是d[(1<<n)-1]
    12 int n;
    13 
    14 void getPal()       //求出所有的回文串
    15 {
    16     int S, i, j;
    17     for(S = 0; S < (1<<n); S++){    //状态S是否回文
    18         bool ok = 1;
    19         int m = 0, buf[maxn];    //临时存储提取出来的字符
    20         for(i = 0; i < n; i++) if((1<<i) & S){    //提取对应字符
    21             buf[m++] = s[i];
    22         }
    23         for(i = 0, j = m-1; i < j; i++, j--){ //判断回文
    24             if(buf[i] != buf[j]){
    25                 ok = 0;
    26                 break;
    27             }
    28         }
    29         ispal[S] = ok;
    30     }
    31 }
    32 
    33 void dp(){
    34     int S, sub;
    35     d[0] = 0;
    36     for(S = 1; S < (1<<n); S++){
    37         d[S] = INF;
    38         for(sub = S; sub > 0; sub = (sub-1) & S){    //sub = (sub-1) & S)保证是集合S中的字母
    39             if(ispal[sub]) d[S] = min(d[S], d[S^sub] + 1);    //S^sub就是剩下的字符
    40         }
    41     }
    42 }
    43 
    44 int main()
    45 {
    46     int T;
    47     scanf("%d", &T);
    48     while(T--){
    49         scanf("%s", s);
    50         n = strlen(s);
    51         getPal();
    52         dp();
    53         printf("%d
    ", d[(1<<n)-1]);
    54     }
    55     return 0;
    56 }

    附贴标程:

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 using namespace std;
     5 
     6 int min(int a,int b){
     7     return a<b ?a :b;
     8 }
     9 
    10 const int MAX_N = 16, INF = 0xffffff;
    11 int n;
    12 int dp[1 << MAX_N][MAX_N][MAX_N]; //rest,i,j
    13 char s[MAX_N + 1];
    14 void work() {
    15     int i,j,k;
    16     scanf("%s", s);
    17     n = strlen(s);
    18 
    19     for (i = 0; i < n; i++) {
    20         for (j = i; j < n; j++) {
    21             dp[0][i][j] = 0;
    22         }
    23     }
    24 
    25     for (int rest = 1; rest < (1 << n); rest++) {
    26         for (i = n - 1; i >= 0; i--) {
    27             for (j = i; j < n; j++) {
    28                 //rest,i,j
    29                 int &ret = dp[rest][i][j] = INF;
    30                 if (i < j)
    31                     ret = min(dp[rest][i + 1][j], dp[rest][i][j - 1]);
    32                 if (s[i] == s[j] && ((rest >> i) & 1) && ((rest >> j) & 1)) {
    33                     int nrest = rest & (~(1 << i)) & (~(1 << j));
    34                     if (nrest == 0)
    35                         ret = min(ret, dp[nrest][i][j] + 1);
    36                     else
    37                         ret = min(ret, dp[nrest][i][j]);
    38                 }
    39             }
    40         }
    41         for (i = n - 1; i >= 0; i--) {
    42             for (int j = i; j < n; j++) {
    43                 dp[rest][i][j] = min(dp[rest][i][j], dp[rest][0][n - 1] + 1);
    44             }
    45         }
    46     }
    47 
    48     cout << dp[(1 << n) - 1][0][n - 1] << endl;
    49 }
    50 
    51 int main() {
    52     int T;
    53     cin >> T;
    54     while (T--) {
    55         work();
    56     }
    57 }
  • 相关阅读:
    第一个java程序
    Java安装
    Maven安装
    Effective Java 3
    gateway + jwt 网关认证
    idea的使用
    线程池的使用
    服务注册发现Eureka
    zookeeperAPI的常用方法
    sss
  • 原文地址:https://www.cnblogs.com/acm-bingzi/p/3231780.html
Copyright © 2020-2023  润新知