• CF79D Password


    CF79D Password 

    挺巧妙的题

    看起来无从下手

    k很小,先不管

    把最终需要亮的看做1,不需要的看做0

    要把全0序列,变成有至多10个1的01序列

    不妨考虑把01序列变回全0序列(这样容易思考)

    区间取反?

    差分变成两个单点取反!

    特殊加入n+1位置,这样便于取反

    首先,两个0取反一定不优,可以用01取反和11取反来得到相同的效果

    01取反,等价于1走到0,11取反,等价于两个1消掉。

    不断两个位置进行取反,一定是为了最后把两个1消掉!

    也就是,其实是两个1的匹配

    1一共只有20个

    最短路建图,f[i][j]表示i和j匹配的最小代价,也即最短路

    一个问题是:不会影响其他位置的值吗?

    发现这个最短路的边,除了起点终点,都恰好xor两次(虽然这样并不优)!不会影响其他的位置的值!

    BFS求最短路

    然后Dp即可

    枚举和S的lowbit进行匹配的点

    O(20*2^20)

    #include<bits/stdc++.h>
    #define reg register int
    #define il inline
    #define fi first
    #define se second
    #define mk(a,b) make_pair(a,b)
    #define numb (ch^'0')
    #define pb push_back
    #define solid const auto &
    #define enter cout<<endl
    #define pii pair<int,int>
    using namespace std;
    typedef long long ll;
    template<class T>il void rd(T &x){
        char ch;x=0;bool fl=false;while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
        for(x=numb;isdigit(ch=getchar());x=x*10+numb);(fl==true)&&(x=-x);}
    template<class T>il void output(T x){if(x/10)output(x/10);putchar(x%10+'0');}
    template<class T>il void ot(T x){if(x<0) putchar('-'),x=-x;output(x);putchar(' ');}
    template<class T>il void prt(T a[],int st,int nd){for(reg i=st;i<=nd;++i) ot(a[i]);putchar('
    ');}
    namespace Modulo{
    const int mod=998244353;
    int ad(int x,int y){return (x+y)>=mod?x+y-mod:x+y;}
    void inc(int &x,int y){x=ad(x,y);}
    int mul(int x,int y){return (ll)x*y%mod;}
    void inc2(int &x,int y){x=mul(x,y);}
    int qm(int x,int y=mod-2){int ret=1;while(y){if(y&1) ret=mul(x,ret);x=mul(x,x);y>>=1;}return ret;}
    }
    //using namespace Modulo;
    namespace Miracle{
    const int N=10000+5;
    const int M=105;
    const int K=22;
    const int inf=0x3f3f3f3f;
    int n,k,m;
    int pos[K],dis[N],cnt;
    int f[K][K];
    int a[N],b[N];
    int dp[(1<<20)+23];
    int q[N],l,r;
    void bfs(int st){
        memset(dis,0x3f,sizeof dis);
        dis[pos[st]]=0;
        l=1,r=0;
        q[++r]=pos[st];
        while(l<=r){
            int x=q[l++];
            for(reg i=1;i<=m;++i){
                int to=x+b[i];
                if(to<=n+1&&dis[to]>dis[x]+1){
                    dis[to]=dis[x]+1;
                    q[++r]=to;
                }
                to=x-b[i];
                if(to>0&&dis[to]>dis[x]+1){
                    dis[to]=dis[x]+1;
                    q[++r]=to;
                }
            }
        }
        for(reg i=1;i<=cnt;++i){
            f[st][i]=dis[pos[i]];
        }
    }
    int num(int p){
        int sz=__builtin_ctz(p);
        return sz+1;
    }
    int main(){
        rd(n);rd(k);rd(m);
        for(reg i=1;i<=k;++i){
            int x;rd(x);
            a[x]=1;
        }
        for(reg i=1;i<=m;++i){
            rd(b[i]);
        }
        for(reg i=n+1;i>=1;--i){
            a[i]^=a[i-1];
            if(a[i]==1) pos[++cnt]=i;
        }
        // prt(a,1,n+1);
        // prt(pos,1,cnt);
        for(reg i=1;i<=cnt;++i){
            // cout<<" bfs i------------ "<<i<<endl;
            bfs(i);
            // prt(f[i],1,cnt);
        }
        memset(dp,0x3f,sizeof dp);
        dp[0]=0;
        for(reg s=1;s<(1<<cnt);++s){
            int sz=__builtin_popcount(s);
            if((sz&1)) continue;
            // cout<<" ss "<<s<<endl;
            int t=s&(-s);
            for(reg tmp=s^t,p=tmp&(-tmp);tmp;tmp=tmp^p,p=tmp&(-tmp)){
                // cout<<" t "<<t<<" num(t) "<<num(t)<<" p "<<p<<" num(p) "<<num(p)<<" fan "<<dp[s^t^p]<<endl;
                dp[s]=min(dp[s],dp[s^t^p]+f[num(t)][num(p)]);
            }
        }
        // prt(dp,0,(1<<cnt)-1);
        if(dp[(1<<cnt)-1]==inf){
            puts("-1");
        }else{
            printf("%d
    ",dp[(1<<cnt)-1]);
        }
        return 0;
    }
    
    }
    signed main(){
        Miracle::main();
        return 0;
    }
    
    /*
       Author: *Miracle*
    */
  • 相关阅读:
    Qt QApplication 类简介--Qt 类简介专题(四)
    回调函数
    C++类型转换总结
    Debug Error
    C++回调函数(callback)的使用
    Nokia5230连接电脑无线上网
    photoshop cs6\cs5找不到扫描仪的解决办法(Twain_32.8BA补丁下载)
    UML类图几种关系的总结
    实现单点登录
    poj 1151Atlantis线段树求矩形面积并解题报告
  • 原文地址:https://www.cnblogs.com/Miracevin/p/10933169.html
Copyright © 2020-2023  润新知