zoukankan      html  css  js  c++  java
  • 19_07_07校内训练[xor]

    题意

    长度为n的数组,上面有k个位置是1,现在有l种长度的连续全1串,要求用最少的次数将这个数组异或成全0的数组。n<=1E5,k<=10,l<=100。


    思考

    先将数组进行异或的差分。可以发现,现在异或上全1串只是将两个端点进行异或。

    接下来求出将每对1变成0的最小代价,之后就是简单状压。

    复杂度O(nkl+2^(2k))。


    代码

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int maxn=2E5+5;
     4 const int inf=23333333;
     5 int n,k,l;
     6 int a[maxn],b[maxn],len[maxn],where[maxn],tot;
     7 int dis[55][55];
     8 int f[maxn],ans[(1<<21)+5];
     9 bool vis[maxn];
    10 void bfs(int S,int num)
    11 {
    12     memset(vis,0,sizeof(vis));
    13     queue<int>Q;
    14     Q.push(S);
    15     vis[S]=1;
    16     for(int i=1;i<=n;++i)
    17         f[i]=inf;
    18     f[S]=0;
    19     while(!Q.empty())
    20     {
    21         int u=Q.front();
    22         Q.pop();
    23         for(int i=1;i<=l;++i)
    24         {
    25             int v=u+len[i],nw=f[u]+1;
    26             if(v>n)
    27                 continue;
    28             if(nw<f[v])
    29             {
    30                 f[v]=nw;
    31                 if(!vis[v])
    32                     Q.push(v),vis[v]=1;
    33             }
    34         }
    35         for(int i=1;i<=l;++i)
    36         {
    37             int v=u-len[i],nw=f[u]+1;
    38             if(v<1)
    39                 continue;
    40             if(nw<f[v])
    41             {
    42                 f[v]=nw;
    43                 if(!vis[v])
    44                     Q.push(v),vis[v]=1;
    45             }
    46         }
    47     }
    48     for(int i=1;i<=tot;++i)
    49         dis[num][i]=f[where[i]];
    50 }
    51 int main()
    52 {
    53     scanf("%d%d%d",&n,&k,&l);
    54     for(int i=1;i<=k;++i)
    55     {
    56         int x;
    57         scanf("%d",&x);
    58         a[x]=1;
    59     }
    60     ++n;
    61     for(int i=1;i<=l;++i)
    62         scanf("%d",&len[i]);
    63     for(int i=1;i<=n;++i)
    64     {
    65         b[i]=a[i]^a[i-1];
    66         if(b[i])
    67             where[++tot]=i;
    68     }
    69     for(int i=1;i<=tot;++i)
    70         bfs(where[i],i);
    71     for(int S=0;S<(1<<tot);++S)
    72         ans[S]=inf;
    73     ans[0]=0;
    74     for(int S=0;S<(1<<tot);++S)
    75     {
    76         for(int i=0;i<tot;++i)
    77         {
    78             for(int j=i+1;j<tot;++j)
    79             {
    80                 if((S&(1<<i))||(S&(1<<j)))
    81                     continue;
    82                 int nS=S|(1<<i)|(1<<j);
    83                 int nw=ans[S]+dis[i+1][j+1];
    84                 ans[nS]=min(ans[nS],nw);
    85             }
    86         }
    87     }
    88     if(ans[(1<<tot)-1]==inf)
    89         printf("-1
    ");
    90     else
    91         printf("%d
    ",ans[(1<<tot)-1]);
    92     return 0;
    93 }
    View Code
  • 相关阅读:
    [debug] 解决在C++编写过程中的“找到一个或多个多重定义的符号”
    调试事件的收集
    [ida]查看某一函数在程序中被谁引用
    IDA+Windbg IDA+OD 连动调试插件
    一个简单的创建被调试进程的案例
    LOAD_DLL_DEBUG_EVENT 时读取 DllName
    【编译系统01】编译器
    [动态规划]石子合并问题
    xBIM 基础15 IFC导出Excel报表
    xBIM 基础14 使用LINQ实现最佳性能(优化查询)
  • 原文地址:https://www.cnblogs.com/GreenDuck/p/11151156.html
Copyright © 2011-2022 走看看