• 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
  • 相关阅读:
    CC.NET+SVN+Msbuild
    react服务端/客户端,同构代码心得
    为什么国人很难出高质量开源
    FKP,一套全栈框架,基于react、webpack、koa1、babel
    嵌入式工程师的发展路线
    浅谈学习单片机的一些职业规划
    关于嵌入式新手面试的一些小技巧
    几点心得送给学习嵌入式的新手
    新手学习嵌入式需要掌握的几点知识点
    从迷茫到转机,一个嵌入式工程师的经历
  • 原文地址:https://www.cnblogs.com/Cw-trip/p/4684855.html
Copyright © 2020-2023  润新知