[noip模拟题]科技节 - 搜索 - 位运算优化

【问题描述】

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

【输入】

      输入文件名为scifest.in。

      输入数据包括多组。

      对于每组数据:

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

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

【输出】

      输出文件名为scifest.out。

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

 

 

【输入输出样例】

scifest.in

scifest.out

3 3

0 1 0

0 0 1

1 0 0

4 4

0 0 0 1

1 0 0 0

1 1 0 1

0 1 0 0

Yes

No

 

【数据范围】

      对于20%的数据,n≤10,m≤200,数据组数≤10;

      对于60%的数据,n≤16,m≤300,数据组数≤100;

      对于100%的数据,n≤16,m≤300,数据组数≤1,000。


  这题开始以为是用动态规划,后来发现n这么小应该使用搜索,后来经老师介绍,如果纯搜索+数组的话只能过6组数据,而加上二进制就可以全过

  boolean数组其实既浪费内存又浪费时间,1个字节8个二进制位,而事实上储存true和false只用1个二进制位,所以用unsigned int类型的32个二进制位

来存储这些true和false的数据。其它都比较简单,直接就发代码了

Code

 1 #include<iostream>
 2 #include<fstream>
 3 #include<algorithm>
 4 #include<cstring>
 5 using namespace std;
 6 #define k 32
 7 typedef bool boolean;
 8 ifstream fin("scifest.in");
 9 ofstream fout("scifest.out");
10 boolean found;
11 int m,n;
12 int buf;
13 typedef struct myData{
14     int peo;
15     unsigned int activities[10];
16 }myData;
17 myData *s;
18 unsigned int ac[10];
19 boolean cmp(const myData& a,const myData& b){
20     return a.peo > b.peo;
21 }
22 boolean init(){
23     if(!(fin>>n>>m)) return false;
24     s = new myData[(const int)(n + 1)];
25     found = false;
26     for(int i = 0;i < n;i++){
27         s[i].peo = 0;
28         memset(s[i].activities, 0, sizeof(s[i].activities));
29         for(int j = 0;j < m;j++){
30             fin>>buf;
31             if( buf == 1 ){
32                 s[i].peo++;
33                 s[i].activities[j/k] += 1 << (j % k);
34             }
35         }
36     }
37     sort(s,s + n,cmp);
38     return true;
39 }
40 void free_MyPointer(){
41     delete[] s;
42 }
43 void find(int vi,unsigned int *sed,int join){
44     if(vi == n){
45         if(join == m) found = true;
46         return ;
47     }
48     unsigned int t[10];
49     boolean aFlag = true;
50     for(int i = 0;i <= m/k;i++){
51         if((sed[i] & s[vi].activities[i]) != 0){
52             aFlag = false;
53             break;
54         }
55         t[i] = sed[i] | s[vi].activities[i];
56     }
57     if(aFlag)    find(vi + 1, t, join + s[vi].peo);
58     if(!found)    find(vi + 1, sed, join);
59 }
60 int main(){
61     while(init()){
62         find(0, ac, 0);
63         if(found)    fout<<"Yes"<<endl;
64         else fout<<"No"<<endl;
65         free_MyPointer();
66     }
67     return 0;
68 }


 

posted @ 2016-07-15 21:41  阿波罗2003  阅读(262)  评论(0编辑  收藏  举报