• 【状压DP】OpenJ_POJ


    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  } 
    状压DP
  • 相关阅读:
    在 Students 的 Index 页面增加列标题链接(排序),分页,过滤和分组功能
    Contoso 大学
    如何搭建MVC + EF 框架
    EF与手写Model的区别以及联系
    報錯:One or more validation errors were detected during model generation:System.Data.Edm.EdmEntityType: : EntityType 'Movie' has no key
    Oracle四舍五入,向上取整,向下取整
    datagrid中设置编辑,删除列是否可以访问
    datagrid中设置编辑,删除列是否可以访问
    C#实现打印
    C#中rpt的数据类型和Oracle中数据类型的匹配
  • 原文地址:https://www.cnblogs.com/itcsl/p/7222525.html
Copyright © 2020-2023  润新知