C17K:Lying Island

链接

题意:

  有n个人,每个人可能会说:

  • 第x个人是好人/坏人
  • 如果第x个人是好人/坏人,则第y个人是好人/坏人

思路:

  状压dp,首先每个人所说的人只能是他前面10个人,所以对于第i个人记录下,他前面十个人的情况。

  对于第i个人,如果他说的话一个状态不冲突,那么i可以由这个状态转移。

  注意:对于“如果第x个人是好人,那么第y个人是坏人 “,那么x是好人,y是好人是不满足的。但是除了x是好人y是坏人这种情况满足,x是坏人,也是满足的。(一定要学好语文!)

 

代码

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<iostream>
 5 #include<cmath>
 6 
 7 using namespace std;
 8 
 9 int dp[5010][1050];
10 char str[50];
11 int k;
12 
13 void work1(int i,int x,int z) {
14     int t = (1 << k);
15     for (int j=0; j<t; ++j) {
16         if (((j>>(x-i+k))&1)==z) dp[i][(j+t)>>1] = max(dp[i][(j+t)>>1],dp[i-1][j]+1);
17         dp[i][j>>1] = max(dp[i][j>>1],dp[i-1][j]); 
18     }
19 }
20 void work2(int i,int x,int y,int z1,int z2) {
21     int t = (1 << k);
22     for (int j=0; j<t; ++j) {
23         int t1 = ((j>>(x-i+k))&1) == z1,t2 = ((j>>(y-i+k))&1) != z2;
24         if (!(t1&&t2)) dp[i][(j+t)>>1] = max(dp[i][(j+t)>>1],dp[i-1][j]+1);
25         dp[i][j>>1] = max(dp[i][j>>1],dp[i-1][j]);
26     }
27 }
28 int main() {
29     int T,n,x,y,z; 
30     scanf("%d",&T);
31     while (T--) {
32         scanf("%d%d",&n,&k);
33         memset(dp,-1,sizeof(dp));
34         for (int j=0,t=(1<<(k-1)); j<t; ++j) dp[1][j] = 0;
35         for (int j=(1<<(k-1)),t=(1<<k); j<t; ++j) dp[1][j] = 1;
36         
37         for (int i=2; i<=n; ++i) {
38             scanf("%s%s%s%d",str,str,str,&x);
39             if (str[0]=='P') {
40                 scanf("%s%s%s",str,str,str);
41                 if (str[0]=='g') z = 1;
42                 else z = 0;
43                 scanf("%s",str);
44                 work1(i,x,z);
45             }
46             else {
47                 scanf("%s%d%s%s%s",str,&x,str,str,str);
48                 if (str[0]=='g') z = 1;
49                 else z = 0;
50                 scanf("%s%s%d%s%s%s",str,str,&y,str,str,str);
51                 work2(i,x,y,z,str[0]=='g');
52                 scanf("%s",str);
53             }
54         }
55         int ans = 0;
56         for (int i=0,t=(1<<k); i<t; ++i) ans = max(ans,dp[n][i]);
57         printf("%d\n",ans); 
58     }
59     return 0;
60 }

 

posted @ 2018-04-28 21:27  MJT12044  阅读(222)  评论(0编辑  收藏  举报