• poj1185


     1 /*状态压缩就是把一系列用二进制表示的状态压缩成一个十进制数*/
     2 #include<stdio.h>
     3 #include<string.h>
     4 #include<iostream>
     5 using namespace std;
     6 int s[65],dp[150][65][65],cont=0,sum[65],map[150];//m为10根据要求每行最多60中状态
     7 bool ok(int x)
     8 {
     9     if(x&(x<<1)) return false;//间隔1的不满足
    10     if(x&(x<<2)) return false;//间隔2的不满足
    11     return true;
    12 }
    13 int getsum(int x)//判断x有几个1,即这种状态能放多少大炮
    14 {
    15     int sum=0;
    16     while(x>0)
    17     {
    18        if(x&1) sum++;
    19         x>>=1;
    20     }
    21     return sum;
    22 }
    23 void init(int n)//初始化所有满足的状态
    24 {
    25     int i;
    26     for(i=0;i<(1<<n);i++)
    27         if(ok(i))
    28         {
    29             s[cont]=i;//记录满足的状态,大炮占的位置为1,山地 位置为0;
    30             sum[cont++]=getsum(i);//记录这种状态可以放多少门大炮
    31         }
    32 }
    33 int max(int a,int b)
    34 {
    35     if(a>b) return a;
    36     return b;
    37 }
    38 int main()
    39 {
    40     int i,j,n,m,k,r;
    41     
    42     while(cin>>n>>m)
    43     {
    44         memset(dp,-1,sizeof(dp));
    45         for(i=0;i<n;i++)
    46         {
    47             for(j=0;j<m;j++)
    48             {
    49                  char c;
    50                 cin>>c;
    51                 //printf("%c ",c);
    52                 //if(j==m-1)     getchar();
    53                 //a[i][j]=c;
    54                 if(c=='H') map[i]|=(1<<j);//记录实际的地形,有山的位置为1;
    55             }
    56         }
    57             init(m);
    58             for(i=0;i<cont;i++)//特别判断第一行;
    59                 if(!(s[i]&map[0])) //s[i]中大炮位置为1,map中山地位置为1,如果想与后的结果不为0说明大炮和山地位置相同,是不满足的,这行是筛选所有满足的状态中符合这个地形的
    60                     dp[0][0][i]=sum[i];//前面的0,0代表第0行的没有前面两行,所以第0行的
    61                 for(r=1;r<n;r++)
    62                     for(i=0;i<cont;i++)//枚举第r行
    63                     {
    64                         if(s[i]&map[r]) continue;//剪枝,如果状态j不满足地形
    65                         for(j=0;j<cont;j++)//枚举第r-1行
    66                         {
    67                             if(s[i]&s[j]) continue;//如果这两行的大炮在同一列
    68                             for(k=0;k<cont;k++)//枚举第r-2行
    69                             {
    70                                 if(s[i]&s[k]) continue;//
    71                                 if(dp[r-1][k][j]==-1) continue;//没这种状态存在
    72                                 dp[r][j][i]=max(dp[r][j][i],dp[r-1][k][j]+sum[i]);
    73                             }
    74                         }
    75                     }
    76 
    77                                   /*状态转移,从i到j,从k到j再从j到i,sum[i]是本行每种状态i的大炮个数,
    78                                 j代表r-1行大炮的放法,i是本行的放法,因为这个关系是一层一层传下来的,
    79                                 所以那么dp[r][j][i]代表的是从开始行到r行的最大炮个数,*/
    80                     int ans = 0;
    81                    for(i = 0; i < cont; i ++)
    82                    for(j = 0; j <cont; j ++)
    83                    ans = max(ans,dp[n-1][i][j]);
    84                    printf("%d
    ",ans);
    85     }
    86       return 0;
    87 }
    88 
    89     
    90 /*
    91 5 4
    92 PHPP
    93 PPHH
    94 PPPP
    95 PHPP
    96 PHHP*/
  • 相关阅读:
    Asp.net的安全问题
    周末了
    GDI+ 取得文本的宽度和高度
    Family的解释
    日语:名词并列
    第一次来入住园里
    All About Floats
    smarty的基本配置
    apache:一个ip绑定多个域名的问题
    CSS Overflow属性详解
  • 原文地址:https://www.cnblogs.com/okboy/p/3227096.html
Copyright © 2020-2023  润新知