现在的位置: 首页 > 综合 > 正文

POJ 1185 炮兵阵地

2019年02月23日 ⁄ 综合 ⁄ 共 1448字 ⁄ 字号 评论关闭

题目链接~~>

做题感悟:这题开始想了很久都没想到怎样解决,百度了一下才明白,真的很经典。

解题思路:

                 解决这种题首先思考一下当前状态(这里设为 i )与哪些状态有关 ? 这题很明显当前状态 i 与 i - 1 , i - 2  有关,so ~ 当操作当前状态时必须从 i - 1 和 i - 2 的 状态转化,你也许想到用 dp [ i ][ S(i - 1) ] [ S (i - 2) ] [ Si ]  来做,但是完全可以用
dp [ i ] [ S( i - 1 ) [ Si ]  = max( dp [ i ] [ S( i - 1 ) ] [ Si ]  , dp [ i - 1 ] [ S( i - 2 ) ] [ i - 1 ]  )  ;
其实只需要三维 dp 就可以了。做的时候要先处理一下每种状态是否满足行的要求,边界条件为 dp [ 1 ] [ 1 ] [ i ] = num [ i ]  ;   i 代表第 i 种状态。

代码:

#include<stdio.h>
#include<queue>
#include<cmath>
#include<string.h>
#include<iostream>
#include<iomanip>
#include<algorithm>
#include<stdlib.h>
using namespace std ;
const int MY = 100 + 10 ;
const int MX = 100 + 10 ;
int n , m , S , p ;
char s[MX][MX] ;
int dp[MX][MX][MX] , a[MX] , num[MX] , key[MX] ;
bool judge(int x) // 判断同行是否可行
{
    if((x & (x << 1))||(x & (x << 2)))
                 return false ;
    return true ;
}
void init()// 初始化
{
    S = 1<<m ;
    p = 1 ;
    for(int i = 0 ;i < S ; i++)
      if(judge(i))
            key[p++] = i ;
}
int count(int x) // 计算 1 的个数
{
    int sum=0 ;
    while(x)
    {
        x &= (x-1) ;
        sum++ ;
    }
    return sum ;
}
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        init() ;
        for(int i = 1 ; i <= n ; i++)
             cin>>(s[i] + 1) ;
        for(int i= 1 ; i <= n ; i++)
        {
            a[i]=0 ; // i 中的不合法状态
            for(int j = 1 ; j <= m ; j++)
                if(s[i][j]=='H')
                      a[i] |= 1<<(j - 1) ;
        }
        memset(dp,-1,sizeof(dp)) ;
        int ans = 0 ;
        for(int i = 1 ; i < p ; i++) // 初始化第一行
        {
            num[i]=count(key[i]) ; // 计算 1 的个数
            if(!(key[i] & a[1])) // 判断是否建在山地上
            {
                dp[1][1][i] = num[i] ;
                ans = max(num[i] , ans) ;
            }
        }

        for(int i = 2 ; i <= n ; i++)
          for(int j = 1 ; j < p ; j++)
          {
              if(key[j] & a[i])  continue ; // 判断是否健在山地上
              for(int t = 1 ; t < p ; t++) // 判断与上一行是否冲突
              {
                  if(key[j] & key[t]) continue ;
                  for(int k = 1 ; k < p ; k++) // 判断与上上一行是否冲突
                  {
                      if(key[j] & key[k]) continue ;
                      if(dp[i-1][t][k] == -1) continue ;
                      dp[i][k][j] = max(dp[i][k][j] , dp[i-1][t][k] + num[j]) ;
                      ans = max(dp[i][k][j] , ans) ;
                  }
              }
          }
          cout<<ans<<endl ;
    }
    return 0 ;
}

抱歉!评论已关闭.