zoukankan      html  css  js  c++  java
  • 9.20题解

    T1

    考虑如果$k==0$,那么他就是一个裸的最长公共子序列,那么我们完全可以把$k$当作第$3$维,压进$dp$数组里,设$dp[i][j][k]$代表$A$串前$i$位和$B$串前$j$位匹配,修改了$k$次的最长公共子序列长度,多加一个转移方程就可以了,复杂度$O(n^3)$

     1 #include<iostream>
     2 #include<cstdio>
     3 #define maxn 305
     4 using namespace std;
     5 int n,k,ans,i,j,l;
     6 char a[maxn],b[maxn];
     7 int dp[maxn][maxn][maxn];
     8 int main()
     9 {
    10     //freopen("1.in","r",stdin);
    11     //freopen("W.out","w",stdout);
    12     scanf("%d%d",&n,&k);
    13     scanf("%s%s",a+1,b+1);
    14     for(i=1;i<=n;++i)
    15         for(j=1;j<=n;++j)
    16             for(l=0;l<=k;++l)
    17             {
    18                 if(a[i]==b[j])  dp[i][j][l]=dp[i-1][j-1][l]+1;
    19                 ans=max(ans,dp[i][j][l]);
    20                 if(!l)  continue;
    21                 dp[i][j][l]=max(dp[i][j][l],dp[i-1][j-1][l-1]+1);
    22                 ans=max(ans,dp[i][j][l]);
    23             }
    24     printf("%d
    ",ans);
    25     return 0;
    26 }
    View Code

    T2

    考场上并没有深入思考这道题,事实上吧,看了题解之后发现他非常非常的简单,一共要四个不同的点,我们可以枚举中间的两个点,假设分别为$x$和$y$,那么这两个点对答案的贡献就是$du[x]{ imes}du[y]$,$du$里不包括对方,这样的话有一个问题就是我们会出现三元环,一个很好的解决方法是$bieset$,这玩意一般情况下都非常好用,得到包含这两个点的三元环的方法是用$bitset$记录和这个点有之间连边的点,然后把$x$和$y$的$bitset$与起来,一的个数就是三元环的数量,复杂度$O(frac{n^3}{32})$

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<bitset>
     5 #define maxn 2000
     6 #define ll long long
     7 using namespace std;
     8 int n,js;
     9 ll ans;
    10 int du[maxn];
    11 char s[maxn];
    12 bitset <maxn> li[maxn];
    13 bitset <maxn> ls;
    14 int main()
    15 {
    16     scanf("%d",&n);
    17     for(int i=1;i<=n;++i)
    18     {
    19         scanf("%s",s+1);
    20         for(int j=1;j<=n;++j)
    21             if(s[j]=='1')  {li[i][j]=1;  du[i]++;}
    22     }
    23     for(int i=1;i<=n;++i)
    24         for(int j=i+1;j<=n;++j)
    25             if(li[i][j])  {ans+=(du[i]-1)*(du[j]-1);  ls=li[i]&li[j];  ans-=ls.count();}
    26     ans=ans*2;  printf("%lld
    ",ans);
    27     return 0;
    28 }
    View Code

    T3

    由于二进制的特性,我们考虑拆点,考虑对于每一个权值,向所有它的子集连边权为$0$的边,一个数和他的子集做与运算得到的一定是他的子集,也可以给这个数往上补一,让每个点向他的权值连边权为$1$的边,权值向点连边权为$0$的边,反过来也可以,一个$0$一个$1$就行,然后就跑最短路就可以了

    还有一个点就是如果把所有的边都建出来,边过于多了,所以说我们不真正建出来,在跑$dj$的时候,记得有这些边就可以

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<vector>
     5 #include<queue>
     6 #define maxn 200200
     7 #define maxm 300300
     8 #define maxx 1300000
     9 #define maxM 700700
    10 #define inf 1061109567
    11 using namespace std;
    12 struct node{
    13     int di,pos;
    14     bool operator < (const node &a)const
    15     {
    16         return a.di<di;
    17     }
    18 };
    19 int n,m,u,v,js;
    20 int head[maxx],to[maxM],xia[maxM],w[maxM];
    21 int val[maxn],dis[maxx];
    22 priority_queue <node> s;
    23 int lowbit(int x)
    24 {
    25     return x&(-x);
    26 }
    27 void add(int x,int y,int z)
    28 {
    29     to[++js]=y;  xia[js]=head[x];  w[js]=z;  head[x]=js;
    30 }
    31 void dj(int x)
    32 {
    33     memset(dis,0x3f,sizeof(dis));
    34     dis[x]=0;  s.push((node){dis[x],x});
    35     while(s.size())
    36     {
    37         node ls=s.top();  s.pop();
    38         if(ls.di!=dis[ls.pos])  continue;
    39         for(int i=head[ls.pos];i;i=xia[i])
    40         {
    41             int lss=to[i];
    42             if(dis[ls.pos]+w[i]<dis[lss])
    43             {
    44                 dis[lss]=dis[ls.pos]+w[i];
    45                 s.push((node){dis[lss],lss});
    46             }
    47         }
    48         if(ls.pos>n)
    49         {
    50             int l=ls.pos-n-1;
    51             for(int j=l;j>0;j-=lowbit(j))
    52             {
    53                 int lsx=l-lowbit(j),lss=lsx+n+1;
    54                 if(dis[ls.pos]<dis[lss])
    55                 {
    56                     dis[lss]=dis[ls.pos];
    57                     s.push((node){dis[lss],lss});
    58                 }
    59             }
    60         }
    61     }
    62 }
    63 int main()
    64 {
    65     scanf("%d%d",&n,&m);
    66     for(int i=1;i<=n;++i)  scanf("%d",&val[i]);
    67     for(int i=1;i<=m;++i)  {scanf("%d%d",&u,&v);  add(u,v,1);}
    68     for(int i=1;i<=n;++i)  {add(i,val[i]+n+1,1);  add(val[i]+n+1,i,0);}
    69     dj(1);
    70     for(int i=1;i<=n;++i)
    71     {
    72         if(dis[i]>=inf)  printf("-1
    ");
    73         else  printf("%d
    ",dis[i]);
    74     }
    75     return 0;
    76 }
    View Code
  • 相关阅读:
    bind智能DNS + bindUI管理系统(mysql + bind dlz)
    什么情况下,英文单词中的k发音变g,t发音变d,p发音变b
    rsyn同步软链接保持不变
    yaml,json,ini这三种格式用来做配置文件优缺点
    自动挡车档位介绍
    "挡位"还是"档位",究竟谁错了
    Gitlab备份与恢复、迁移与升级
    树的名称大全
    手动档正确换档手势
    gitlab HA集群
  • 原文地址:https://www.cnblogs.com/hzjuruo/p/11679261.html
Copyright © 2011-2022 走看看