zoukankan      html  css  js  c++  java
  • gym101343J. Husam and the Broken Present 2 (状压DP)

    题意:给定n个串 每个串长度不超过100 

       找到一个新串 使得这n个串都是它的字串 输出这个新串的最小长度

    题解:n是15 n的阶乘的复杂度肯定不行 就想到了2的15次方的复杂度

       想到了状压但是不知道怎么维护 所以加一维就好了 dp[i][j]表示当前状态为i 且末尾是第j个串

           转移简直弱智 预处理val[i][j]表示第i个串和第j个串拼在一起会节省的长度 那么答案最后就是总长度减去节省最大的长度了

       然后还要注意一下包含的问题 假如1 2 3,2 3 4 5和3 4这三个串3 4是被包含的

       但是你转移的时候1 2 3和2 3 4 5接在一起后变成 1 2 3 4 5包含了3 4但是此时的状态还是只用了第1个和第2个串的状态

       所以把包含的串去重一下就好了... 弱智这都写了四个小时

    #include <bits/stdc++.h>
    using namespace std;
    
    int vis[20];
    int num[20];
    int q[20][105];
    int val[20][20];
    int dp[70000][20];
    
    int main()
    {
        int n;
        scanf("%d", &n);
    
        int ans = 0;
        for(int i = 1; i <= n; i++)
        {
            scanf("%d", &q[i][0]);
            for(int j = 1; j <= q[i][0]; j++) scanf("%d", &q[i][j]);
        }
        for(int i = 1; i <= n; i++) vis[i] = 1;
    
        int cnt = 0;
        for(int i = 1; i <= n; i++)                //去重
        {
            if(!vis[i]) continue;
            for(int j = 1; j <= n; j++)
            {
                if(i == j) continue;
                if(!vis[j]) continue;
    
                if(q[i][0] >= q[j][0])
                {
                    for(int k = 1; k + q[j][0] - 1 <= q[i][0]; k++)
                    {
                        bool f = true;
                        for(int kk = 1; kk <= q[j][0]; kk++)
                        {
                            if(q[i][k + kk - 1] == q[j][kk]) continue;
                            else {f = false; break;}
                        }
                        if(f) {vis[j] = 0; break;}
                    }
                }
            }
        }
    
        for(int i = 1; i <= n; i++) if(vis[i]) cnt++;
    
        int zn = 0;
        for(int i = 1; i <= n; i++) if(vis[i]) num[++zn] = i;
    
        for(int i = 1; i <= zn; i++)
        {
            for(int j = 0; j <= q[num[i]][0]; j++) q[i][j] = q[num[i]][j];
            ans += q[i][0];
        }
    
        for(int i = 1; i <= cnt; i++)          //预处理价值
        {
            for(int j = 1; j <= cnt; j++)
            {
                if(i == j) continue;
                val[i][j] = 0;
                for(int k = 1; k <= q[i][0]; k++)
                {
                    if(q[i][k] == q[j][1])
                    {
                        bool f  = true;
                        for(int kk = 1; kk + k <= q[i][0]; kk++)
                        {
                            if(q[i][k + kk] == q[j][kk + 1]) continue;
                            else { f = false; break;}
                        }
                        if(f) {val[i][j] = q[i][0] - k + 1; break;}
                    }
                }
            }
        }
        memset(dp, 0, sizeof(dp));
    
        int sta = (1 << cnt) - 1;
        for(int i = 0; i <= sta; i++)
        {
            memset(vis, 0, sizeof(vis));
            for(int j = 0; j < n; j++)
            {
                int c = (i >> j) & 1;
                if(c == 1) vis[j + 1] = 1;
            }
    
            for(int j = 1; j <= n; j++)
            {
                if(vis[j]) continue;
                int v = (1 << (j - 1));
    
                for(int k = 1; k <= n; k++)
                {
                    if(!vis[k]) continue;
                    dp[i + v][j] = max(dp[i + v][j], dp[i][k] + val[k][j]);
                }
            }
        }
    
        int zd = 0;
        for(int i = 1; i <= cnt; i++) zd = max(zd, dp[sta][i]);
        printf("%d
    ", ans - zd);
        return 0;
    }
    
    /*
    3
    3 1 2 3
    2 3 4
    4 2 3 4 5
    */
    View Code
  • 相关阅读:
    2016年3月9日~10日,杨学明老师为武汉某著名通信企业提供内训课程服务!
    打造高效率产品测试体系--产品测试管理(深圳,2016.3.18~19)
    互联网产品上线前,做些什么——产品、开发、测试的视角
    2016年1月16日,《互联网项目管理高级实务》内训在上海某高科技企业成功举办!
    用C++对C++语法格式进行分析
    mysql主从配置
    Windows Zip/CentOS/Radhat系统安装Mysql5.7.x方法
    c++预声明类引发的无法解析外部符号问题
    解决VS2015单元测试“未能设置用于运行测试的执行上下文”问题
    扩展Linux磁盘空间
  • 原文地址:https://www.cnblogs.com/lwqq3/p/8995720.html
Copyright © 2011-2022 走看看