2020-2-2赛

排列组合终于用上了,但是我只是能从0到n-1,所以要改成1-n才对,但对于这道题,只用找集合数,所以不影响

问题 C: 组合数
时间限制: 1 Sec 内存限制: 128 MB
[提交] [状态]
题目描述
从 1 到 N 的整数中挑选一些数,组成集合的方案数是可算的。如果加上 M 个限制:某 2 个数不能 同时选又要怎样计算?
输入
第一行包含 2 个整数 N 和 M,1≤N≤20,1≤M≤400。
下面 M 行,每行 2 个不同的整数 a 和 b 表示这 2 个数不能同时选。1≤a,b≤N,有些限制可能出现多次。

输出
一个整数。
样例输入 Copy
【样例1】
3 2
1 2
2 3
【样例2】
3 3
1 2
1 3
2 3
样例输出 Copy
【样例1】
5
【样例2】
4

#include<bits/stdc++.h>
using namespace std;
int A[25][25],B[25],ans=0;
int main()
{
    int n,m;
    scanf("%d %d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        int a,b;
        scanf("%d %d",&a,&b);
        A[a-1][b-1]=1;
        A[b-1][a-1]=1;
    }
    for(int wei=1;wei<=n;wei++)//不知道算不算空集合
    {
    for(int i=0;i<(1<<n);i++)
    {
        int kk=i,num=0;//num计算位数,也就是下标
        while(kk)
        {
            kk=kk&(kk-1);//计算1 的个数,自动去最后面那个1
            num++;
        }
        if(num==wei)
        {
            int cnt=1;
            for(int j=0;j<n;j++)
            {
                if(i&(1<<j))
                {
                    B[cnt]=j;
                    cnt++;
                }
            }
            int flag=1;
            for(int j=1;j<cnt;j++)//check
            {
               for(int k=j+1;k<cnt;k++)
               {
                   if(A[B[j]][B[k]]==1)
                   {
                       flag=0;
                       break;
                   }
               }
            }
            if(flag==1)
            {
//                for(int j=1;j<cnt;j++)
//                    printf("%d",B[j]);
//                printf("\n");
                ans++;
            }
         }

   }
    }
    printf("%d",ans+1);//空集
    return 0;
}

组合数(zhs) [nhoi 2016 T1]
【题目描述】

从 1 到 N 的整数中挑选一些数,组成集合的方案数是可算的。如果加上 M 个限制:某 2 个数不能

同时选又要怎样计算?

【输入格式】

第一行包含 2 个整数 N 和 M,1≤N≤201≤M≤400。

下面 M 行,每行 2 个不同的整数 a 和 b 表示这 2 个数不能同时选。1≤a,b≤N,有些限制可能出现多次。

【输出格式】

一个整数。

============================================

        看起来是要求组合,但没规定长度,233。那就二进制枚举就行了。检查是400次,看起来挺危险,其实数据不可能那么极端,就这样就过了。

        PS:考试时,我写了个递推,f[i][j]=f[i-1][j+1]+f[i-1][j+2]+...+f[i-1][n],如果i,j有限制就不加。后来知道了,这样只能保证相邻的没有限制,所以狗带了。

============================================

#include <algorithm>
#include <iostream>
#include <fstream>
#include <cstdio>

using namespace std;

const int ML=500;

int f[ML],a[ML],b[ML];

int main()
{
ios::sync_with_stdio(false);

freopen("zhs.in","r",stdin);
freopen("zhs.out","w",stdout);

int n,m; cin>>n>>m;

for (int i=0; i<m; i++)
{
int a,b; cin>>a>>b;
f[i]=(1 << a-1 ) | (1 << b-1); //有第0位,所以要减1
}

long long ans=0;

for (int i=0; i<(1<<n); i++)
{
int ff=1;

for (int j=0; j<m; j++)
if ((i & f[j])==f[j]) //检查
{ ff=0; break; } //记得break哦

ans+=ff;
}

cout<<ans;

return 0;
}


发布了32 篇原创文章 · 获赞 1 · 访问量 1351

猜你喜欢

转载自blog.csdn.net/QXK_Jack/article/details/104145912