2 条题解

  • 0
    @ 2025-10-8 16:52:11

    解法一:基础动态规划(超内存180M)

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    int d[30];
    LL f[21][1<<20];
    bool mp[30][30];
    int main()
    {
        d[1]=1;for(int i=2;i<=20;i++)d[i]=d[i-1]*2;
        int n,m;scanf("%d%d",&n,&m);
        memset(mp,0,sizeof(mp));
        for(int i=1;i<=n;i++)
        {
            int k;scanf("%d",&k);
            for(int j=1;j<=k;j++)
            {
                int x;scanf("%d",&x);
                mp[i][x]=1;
            }
        }
        memset(f,0,sizeof(f)); 
        for(int i=1;i<=m;i++)if(mp[1][i]==1)f[1][d[i]]=1;
        for(int i=2;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
                if(mp[i][j])
                {
                    for(int k=0;k<(1<<m);k++)
                        if((k&d[j]))
                            f[i][k]+=f[i-1][k-d[j]];
                }
        }
        LL ans=0;
        for(int i=0;i<(1<<m);i++)ans+=f[n][i];
        printf("%lld\n",ans);
        return 0;
    }
    

    解法二:滚动数组优化(内存18M)

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    int d[30];
    LL f[2][1<<20];
    bool mp[30][30];
    int main()
    {
        d[1]=1;for(int i=2;i<=20;i++)d[i]=d[i-1]*2;
        int n,m;scanf("%d%d",&n,&m);
        memset(mp,0,sizeof(mp));
        for(int i=1;i<=n;i++)
        {
            int k;scanf("%d",&k);
            for(int j=1;j<=k;j++)
            {
                int x;scanf("%d",&x);
                mp[i][x]=1;
            }
        }
        memset(f,0,sizeof(f)); 
        for(int i=1;i<=m;i++)if(mp[1][i]==1)f[1][d[i]]=1;
        int t=1;
        for(int i=2;i<=n;i++)
        {
            t=1-t;
            memset(f[t],0,sizeof(f[t])); 
            for(int j=1;j<=m;j++)
                if(mp[i][j])
                {
                    for(int k=0;k<(1<<m);k++)
                        if((k&d[j]))
                            f[t][k]+=f[1-t][k-d[j]];
                }
        }
        LL ans=0;
        for(int i=0;i<(1<<m);i++)ans+=f[t][i];
        printf("%lld\n",ans);
        return 0;
    }
    
    • 0
      @ 2025-10-8 16:51:56
      #include<bits/stdc++.h>//超内存180M
      using namespace std;
      typedef long long LL;
      int d[30];
      LL f[21][1<<20];
      bool mp[30][30];
      int main()
      {
          d[1]=1;for(int i=2;i<=20;i++)d[i]=d[i-1]*2;
          int n,m;scanf("%d%d",&n,&m);
          memset(mp,0,sizeof(mp));
          for(int i=1;i<=n;i++)
          {
              int k;scanf("%d",&k);
              for(int j=1;j<=k;j++)
              {
                  int x;scanf("%d",&x);
                  mp[i][x]=1;
              }
          }
          memset(f,0,sizeof(f)); 
          for(int i=1;i<=m;i++)if(mp[1][i]==1)f[1][d[i]]=1;
          for(int i=2;i<=n;i++)
          {
              for(int j=1;j<=m;j++)
                  if(mp[i][j])
                  {
                      for(int k=0;k<(1<<m);k++)
                          if((k&d[j]))
                              f[i][k]+=f[i-1][k-d[j]];
                  }
          }
          LL ans=0;
          for(int i=0;i<(1<<m);i++)ans+=f[n][i];
          printf("%lld\n",ans);
          return 0;
      }

      #include<bits/stdc++.h>//用滚动数组,内存18M
      using namespace std;
      typedef long long LL;
      int d[30];
      LL f[2][1<<20];
      bool mp[30][30];
      int main()
      {
          d[1]=1;for(int i=2;i<=20;i++)d[i]=d[i-1]*2;
          int n,m;scanf("%d%d",&n,&m);
          memset(mp,0,sizeof(mp));
          for(int i=1;i<=n;i++)
          {
              int k;scanf("%d",&k);
              for(int j=1;j<=k;j++)
              {
                  int x;scanf("%d",&x);
                  mp[i][x]=1;
              }
          }
          memset(f,0,sizeof(f)); 
          for(int i=1;i<=m;i++)if(mp[1][i]==1)f[1][d[i]]=1;
          int t=1;
          for(int i=2;i<=n;i++)
          {
          	t=1-t;
          	memset(f[t],0,sizeof(f[t])); 
              for(int j=1;j<=m;j++)
                  if(mp[i][j])
                  {
                      for(int k=0;k<(1<<m);k++)
                          if((k&d[j]))
                              f[t][k]+=f[1-t][k-d[j]];
                  }
          }
          LL ans=0;
          for(int i=0;i<(1<<m);i++)ans+=f[t][i];
          printf("%lld\n",ans);
          return 0;
      }
      • 1

      *【状态压缩DP】二分图匹配的方案数

      信息

      ID
      542
      时间
      1000ms
      内存
      256MiB
      难度
      8
      标签
      递交数
      137
      已通过
      26
      上传者