https://vjudge.net/contest/171652#problem/K
【题意】
- 小岛上有n个人,有些是好人(一定是真话),有些是坏人(可能是真话也可能是假话),现在要判断最多有多少好人
- 每个人说话有四种形式:
- 1. Person i: Person x is a good guy.
- 2. Person i: Person x is a bad guy.
- 3. Person i: If person x is a good guy, person y is a good guy.
- 4. Person i: If person x is a bad guy, person y is a bad guy.
- 从2到n依次考察n-1个人
- 对于第i个人,他知道的信息只有从max(i-k,1)到i-1
- 0 <= N <= 5000,1 <= K <= 10
【思路】
- 对于第i个人,他只知道max(i-k,1)到i-1个人的信息,k最多是10。用1表示好人,0表示坏人,max(i-k,1)到i-1个人的信息可以状压保存,高位是编号大的人
- dp[i][j]表示考察到第i个人时,状态为j(最高位为i的状态)时好人最多是多少个
- 初始化:对于第一个人,可能是好人也可能是坏人,所以第k位为1时,第一个人是好人,dp为1;第k位为0时,dp为0
- 状态转移:如果第i个人说的话与max(i-k,1)到i-1本身的信息相符,说第i个人可能是好人,状态转移为,右移并且最高位置1,好人数增加一个;不管相符还是不符,第i个都可能是坏人,状态转移为,右移一位最高位置0,好人数不增加
- 注意第四种说话方式时,只有if 符合而then不符合,可以确定当前人一定不是好人,否则都有可能是好人
【Accepted】
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<string> 5 #include<algorithm> 6 #include<cmath> 7 8 using namespace std; 9 const int maxn=5e3+2; 10 int dp[maxn][1030]; 11 int n,k; 12 int main() 13 { 14 int T; 15 scanf("%d",&T); 16 while(T--) 17 { 18 memset(dp,-1,sizeof(dp)); 19 scanf("%d%d",&n,&k); 20 for(int i=0,mx=(1<<(k-1));i<mx;i++) 21 { 22 dp[1][i]=0; 23 } 24 for(int i=(1<<(k-1)),mx=(1<<k);i<mx;i++) 25 { 26 dp[1][i]=1; 27 } 28 for(int i=2;i<=n;i++) 29 { 30 char str[10]; 31 int x,y,dx,dy; 32 scanf("%s%d%s%s",str,&x,str,str); 33 if(str[0]=='P') 34 { 35 scanf("%d%s%s%s",&x,str,str,str); 36 if(str[0]=='g') dx=1; 37 else dx=0; 38 for(int j=0,mx=(1<<k);j<mx;j++) 39 { 40 if(((j>>(x-i+k))&1)==dx) 41 { 42 dp[i][(j+mx)>>1]=max(dp[i][(j+mx)>>1],dp[i-1][j]+1); 43 } 44 dp[i][j>>1]=max(dp[i][j>>1],dp[i-1][j]); 45 } 46 scanf("%s",str); 47 } 48 else 49 { 50 scanf("%s%d%s%s%s",str,&x,str,str,str); 51 if(str[0]=='g') dx=1; 52 else dx=0; 53 scanf("%s%s%d%s%s%s",str,str,&y,str,str,str); 54 if(str[0]=='g') dy=1; 55 else dy=0; 56 scanf("%s",str); 57 for(int j=0,mx=(1<<k);j<mx;j++) 58 { 59 if(!((((j>>(x-i+k))&1)==dx)&&(((j>>(y-i+k))&1)!=dy))) 60 { 61 dp[i][(j+mx)>>1]=max(dp[i][(j+mx)>>1],dp[i-1][j]+1); 62 } 63 dp[i][j>>1]=max(dp[i][j>>1],dp[i-1][j]); 64 } 65 } 66 } 67 int ans=0; 68 for(int i=0,mx=(1<<k);i<mx;i++) 69 { 70 ans=max(ans,dp[n][i]); 71 } 72 printf("%d ",ans); 73 } 74 return 0; 75 }