• 科技节(位运算)


    【问题描述】

          一年一度的科技节即将到来。同学们报名各项活动的名单交到了方克顺校长那,结果校长一看皱了眉头:这帮学生热情竟然如此高涨,每个人都报那么多活动,还要不要认真学习了?!这样不行!……于是,校长要求减少一些活动,使每位学生只能参加一项(一名同学要参加某活动,必须已报名且该活动未被去掉)。当然,他也不希望哪位同学因此不能参加任何活动。他想知道自己的方案能否实行。

    【输入】

          输入文件名为scifest.in。

          输入数据包括多组。

          对于每组数据:

          第一行两个正整数n和m,分别表示活动数和学生数。

          接下来n行,每行m个为0或1的数。第i+1行第j列的数若为1,表示j同学报名参加活动i,否则表示j同学没有报名参加活动i。

    【输出】

          输出文件名为scifest.out。

    对于每组数据输出一行,若校长方案可行则输出“Yes”,否则输出“No”。(均不包括引号)

    【样例输入1】

    3 3

    0 1 0

    0 0 1

    1 0 0

    4

    0 0 0 1

    1 0 0 0

    1 1 0 1

    0 1 0 0

    【样例输出1】

    Yes

    No

    位运算代码:

    #include<cstdio>
    #include<iostream>
    #include<cmath>
    #include<cstring>
    using namespace std;
    long x[20][10];
    long h[20];//一个活动的学生总数
    long n,m;
    long k=0;
    int c;char yes=false;
    void solve(long p,long qw[10],long per)//选第P个,前数组,完成的人数
    {
      if(yes==true)return ;
      if(p==n)
      {
        if(per==m)
        {
          yes=true;
          return ;
        }
        return ;
      }
    long t[10];
      for(k=0;k<=9;k++)
      {
        if((qw[k]&x[p][k])>0)break;
        t[k]=qw[k]|x[p][k];
      }
      if(k==10)solve(p+1,t,per+h[p]);
      if(yes==false) solve(p+1,qw,per);
    }
    int main()
    {
      ios::sync_with_stdio(false);
      freopen("scifest.in","r",stdin);
      freopen("scifest.out","w",stdout);
      while(cin>>n>>m)//活动数,学生数
      {
        memset(x,0,sizeof(x));
        memset(h,0,sizeof(h));
        yes=false;
        for(int i=0;i<=n-1;i++)
        {
          h[i]=0;
          for(int j=0;j<=m-1;j++)
          {
            cin>>c;
            if(c==1)
            {
              x[i][j/31]+=1<<(j%31);
              h[i]++;
            }
          }
        }
        for(int i=0;i<=n-2;i++)
        for(int j=i+1;j<=n-1;j++)
        if(h[i]<h[j])//降序
        {
          k=h[i];h[i]=h[j];h[j]=k;
          for(int q=0;q<=9;q++)
        {
            k=x[i][q];x[i][q]=x[j][q];x[j][q]=k;
          }
        }
        solve(0,x[19],0);
        if(yes==true)cout<<"Yes"<<endl;
        else cout<<"No"<<endl;
      }
    }

    感想:此题一开始根本没想到用位运算,看到题后先想到的是搜索。如果用搜索的话,还要用排序将活动选的人多的排在前面降序,这样剪枝效果很好,我也没有想到。。。。以后看到这种0、1的题后,我应该先想一下能不能用位运算做(虽然掌握不熟练。)

  • 相关阅读:
    快逸报表调用存储过程(SqlServer)
    一个睡五分钟等于六个钟头的方法 (转)
    Windows Live Writer For Windows Server 2003
    设计模式装饰者模式
    SqlServerCUBE
    Android 70道面试题汇总不再愁面试
    说服力:让你的PPT会说话
    亮剑Java项目开发案例导航
    初入社会必知的88个潜规则
    android UI进阶之仿iphone的tab效果2
  • 原文地址:https://www.cnblogs.com/937337156Zhang/p/5675239.html
Copyright © 2020-2023  润新知