主角光环

题目大意:
  有n个人挨打,每个人有一个互不相同编号。
  对方事先告诉你它每次会打哪些编号的人。
  每次我们可以保护所有已经被打过的人或者保护一个没被打过的人。
  如果一个人被打两次就会死掉。
  有两个人因为体质特殊,一次都不能打。
  问在没有人牺牲的情况下,有多少种安排这两个人编号的方法(两个人交换算同一种)。

思路:
  乱搞。
  枚举每一个人,然后倒序枚举每一轮打人的情况。
  对于每个人,在保证它不会被打的情况下维护已经被打的人的集合。
  方便起见,假装这个人已经被打过一次。
  对于每一轮打人的情况,统计有多少个人已经被打过一次,设被打一次的人数为cnt。
  如果cnt=0,没有人被打过,那么保护所有将要被打的人。
  如果cnt=1,自己被打过一次,就先保护自己,让剩下来所有人挨打。
  如果cnt>1,除自己以外还有人已经被打过,如果保护自己,那么另一个人就得牺牲;如果保护另一个人,自己只能被打一次。所以不管怎样都得死,这个位置不适合特殊体质。
  最后枚举每两个位置,判断一下两个是否都适合特殊体质,以及因为这两个人而被挨打一次的人有没有交集。
  如果有交集,那么就相当于交上面的人被打了两次。

 1 #include<cstdio>
 2 #include<cctype>
 3 #include<vector>
 4 #include<bitset>
 5 inline int getint() {
 6     register char ch;
 7     while(!isdigit(ch=getchar()));
 8     register int x=ch^'0';
 9     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
10     return x;
11 }
12 const int N=1001,M=10001;
13 std::vector<int> kill[M];
14 std::bitset<N> b[N];
15 bool hurt[N];
16 int main() {
17     const int n=getint(),m=getint();
18     for(register int i=1;i<=m;i++) {
19         for(register int k=getint();k;k--) {
20             kill[i].push_back(getint());
21         }
22     }
23     for(register int i=1;i<=n;i++) {
24         b[i].set(i);
25         for(register int j=m;j;j--) {
26             int cnt=0;
27             for(register unsigned k=0;k<kill[j].size();k++) {
28                 cnt+=b[i][kill[j][k]];
29             }
30             if(!cnt) continue;
31             if(cnt==1) {
32                 for(register unsigned k=0;k<kill[j].size();k++) {
33                     b[i].set(kill[j][k]);
34                 }
35             } else {
36                 hurt[i]=true;
37                 break;
38             }
39         }
40     }
41     int ans=0;
42     for(register int i=1;i<=n;i++) {
43         if(hurt[i]) continue;
44         for(register int j=i+1;j<=n;j++) {
45             if(hurt[j]) continue;
46             if((b[i]&b[j]).none()) ans++;
47         }
48     }
49     printf("%d\n",ans);
50     return 0;
51 }

 

posted @ 2017-10-25 13:07  skylee03  阅读(178)  评论(0编辑  收藏  举报