zoukankan      html  css  js  c++  java
  • CF 544E(状压

    题目:若干长度相同的字符串,如果一个字符串至少有一个字符与其他字符串这一位的字符都不一样,那它就是好记的,现在问把整合集合都变成好记的最小花费。

    思路:虽然一看就是状压,但是有些地方没理清楚导致一直过不了,首先因为最多有20个字符串而字符集有26,改一个字符肯定可以不与其他字符冲突。然后状态转移中分改变单个字符和该列同种字符两种情况。注意改整列的时候即使已经不冲突的串也要改,因为该列的字符依然是冲突的。对于第二种情况的花费需要预处理一下,不然虽然是常数但是套在状压的复杂度里面立马超时,改成预处理后时间变成了170ms,可见有些常数可以起到关键作用。

    #include<iostream>
    #include<map>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<vector>
    #include<queue>
    #include<stack>
    #include<functional>
    #include<set>
    #include<cmath>
    #define pb push_back
    #define fs first
    #define se second
    #define sq(x) (x)*(x)
    #define eps 0.0000000001
    using namespace std;
    typedef long long ll;
    typedef pair<ll,ll> P;
    int n,m;
    string s[30];
    int c[30][30];
    int c2[30][30];
    int c3[30][30];
    ll dp[1<<21];
    inline int lowbit(int x){
        for(int i=0;i<32;i++){
            if(x&1) return i;
            x>>=1;
        }
        return 0;
    }
    int main(){
        freopen("/home/files/CppFiles/in","r",stdin);
        /*    std::ios::sync_with_stdio(false);
            std::cin.tie(0);*/
        cin>>n>>m;
        for(int i=0;i<n;i++) cin>>s[i];
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                scanf("%d",&c[i][j]);
            }
        }
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                int maxx=0,sum=0,mask=0;
                for(int k=0;k<n;k++){
                    if(s[j][i]==s[k][i]){
                        mask+=(1<<k);
                        maxx=max(c[k][i],maxx);
                        sum+=c[k][i];
                    }
                }
                c2[j][i]=sum-maxx;
                c3[j][i]=mask;
            }
        }
        memset(dp,0x3f,sizeof dp);
        dp[(1<<n)-1]=0;
        for(int stg=(1<<n)-1;stg>0;stg--){///没处理的是1,处理过的是0
            int u=lowbit(stg);
            for(int w=0;w<m;w++){
                int dif1=(1<<u);
                if(dif1>stg) return 1;
                ll &val=dp[stg-dif1];
                val=min(val,dp[stg]+c[u][w]);
                ll &val2=dp[stg&(~c3[u][w])];
                val2=min(val2,dp[stg]+c2[u][w]);
            }
        }
        cout<<dp[0]<<endl;
        return 0;
    }
    View Code
  • 相关阅读:
    git
    node cheerio
    Git是目前世界上最先进的分布式版本控制系统
    精华 ionic入门之色彩、图标、边距和界面组件:列表
    如何将腾讯视频的qlv格式转换为mp4格式
    php无限级分类实战——评论及回复功能
    Yii2 前后台登陆退出分离、登陆验证
    linux 更改文件所属用户及用户组
    wdcp 开启某个Mysql数据库远程访问
    Rem实现自适应初体验
  • 原文地址:https://www.cnblogs.com/Cw-trip/p/4684855.html
Copyright © 2011-2022 走看看