poj 1185 炮兵阵地

题目链接

题意:在N*M的网格地图上部署炮兵部队。地图的每一格可能是山地(用"H" 表示),也可能是平原(用"P"表示),如下图。在每一格平原地形上最多可以布置一支炮兵部队(山地上不能够部署炮兵部队);一支炮兵部队在地图上的攻击范围如图中黑色区域所示: 


如果在地图中的灰色所标识的平原上部署一支炮兵部队,则图中的黑色的网格表示它能够攻击到的区域。炮兵的攻击范围不受地形的影响。 
现在,如何部署炮兵部队,使得任何一支炮兵部队都不在其他支炮兵部队的攻击范围内,在整个地图区域内最多能够摆放多少我军的炮兵部队。

#include<stdio.h>
#include<stdlib.h>
#include<iostream>
#include<string>
using namespace std;

/** 每行摆放炮兵的方法数的最大值 */
#define INF 70

/** 总行数的最大值 */
#define nMAX 103

/** 每一行炮兵的合法的摆放状态 */
int state[INF];				

/** 每一种摆放方法的炮兵,state[i]这一摆放方法中炮兵总数为count[i] */
int count[INF];				

/** f[i][j][k] 表示在上一行以state[k] 的方法摆放的前提下,第i 行以state[j] 的方法摆放的方法总数 */
int f[nMAX][INF][INF];		

/** map数组是输入的地形数据的压缩 */
int map[nMAX];			
	
int main()
{
	/** n * m 的网格地图 */
	int m, n;	
	scanf("%d%d", &n, &m);						

	/** 对输入的地形数据压缩存储 */
	for( int i = 1; i <= n; i ++ ){
		char str[20];
		scanf("%s", str);
		for( int j = 0; j < m; j ++ ){			
			if( str[j] == 'P' )
				map[i] = ( map[i] << 1 ) + 1;
			else map[i] = ( map[i] << 1 ) + 0;
		}
	}

	/** size表示每行允许摆放炮兵的情况数 */
	int size = 0;;

	/* 对size的数值进行计算,
	 * 枚举从0 到 1 << m 的所有数,每个数的二进制表示中的1 表示在
	 * 该处摆放炮兵,0 表示不摆放。
	 * 摆放遵循的规则是:不允许两个炮兵之间的间距 < 2
	 */
	for( i = 0; i < ( 1 << m ); i ++ ){
		int cc = 0;
		int flag = 0;
		int ii = i;
		while( ii > 0 ){
			
			if( ( ii & 1 ) == 1 ){
				if( flag > 0 )
					break;
				else flag = 2;
				cc ++;
			}
			else flag --;
			ii = ii >> 1;
		}
		if( ii == 0 ){
			count[size] = cc;

		    /** 初始化第一行 */
			if( ( map[1] | i ) == map[1] )
				f[1][size][0] = cc;

			state[size++] = i;			
		}
	}	

	/** 对行进行循环 */
	for( i = 2; i <= n; i ++ )

		/** 对上一行的摆放状态进行循环 */
		for( int k1 = 0; k1 < size; k1 ++ )

			/** 对上两行的摆放状态进行循环 */
			for( int k2 = 0; k2 < size; k2 ++ )

				/** 若该种上一行和上两行的摆放状态合理 */
				if( f[i - 1][k1][k2] > 0 )

					/** 对当前行的摆放状态进行循环 */
					for( int j = 0; j < size; j ++ )

						/* 若当前行的这一摆放状态与前一行和前两行的摆放状态都不冲突
						 * 且和地形也不冲突,则比较大小后更新 
						 * f[i][j][k1] = f[i - 1][k1][k2] + count[j];
					     */
						if( ( state[k1] & state[j] ) == 0 && ( state[k2] & state[j] ) == 0 )
							if( ( map[i] | state[j] ) == map[i] )
								if( f[i][j][k1] < f[i - 1][k1][k2] + count[j] )
									f[i][j][k1] = f[i - 1][k1][k2] + count[j];

	/** 计算第i 行的各种摆放方式中炮兵数的最大值 */
	int max = 0;
	for( i = 0; i < size; i ++ ){	
		for( int j = 0; j < size; j ++ )
			if( f[n][i][j] > max )
				max = f[n][i][j];
	}
	printf("%d\n", max );

	return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值