- 1、本文档共3页,可阅读全部内容。
- 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
- 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
1185解题报告,acmpoj
1185炮兵阵地解题报告
唐帆
题目简介
司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队。一个N*M的地图由N行M列组成,地图的每一格可能是山地(用H 表示),也可能是平原(用P表示)。
在每一格平原地形上最多可以布置一支炮兵部队(山地上不能够部署炮兵部队);一支炮兵部队在地图上的攻击范围如图中黑色区域所示:
如果在地图中的灰色所标识的平原上部署一支炮兵部队,则图中的黑色的网格表示它能够攻击到的区域:沿横向左右各两格,沿纵向上下各两格。图上其它白色网格均攻击不到。从图上可见炮兵的攻击范围不受地形的影响。
现在,将军们规划如何部署炮兵部队,在防止误伤的前提下(保证任何两支炮兵部队之间不能互相攻击,即任何一支炮兵部队都不在其他支炮兵部队的攻击范围内),在整个地图区域内最多能够摆放多少我军的炮兵部队。
题意分析
本题给出网格阵地的规格M*N及具体山平原地区分布状况,求无误伤情况下最多可排放多少火力。
由本题炮兵间相互攻击规则易联想到八皇后问题,故首先考虑深度搜索加剪枝:从网格阵地顶点到最后一个点逐点逐状态(HorP,是否存在炮兵)遍历,可以用递归实现,亦可利用非递归加栈型存储结构(遍历过程类似迷宫问题求解)。但在将此想法实现的过程中遇到以下几个问题:
对各点个状态之间的相互影响难以判断。不同于八皇后问题最多只需判断7次是否存在影响(暨放入最后一个皇后时,遍历前7个看是否存在攻击问题),本案最多可能判断10*100-1次;
对各个状态的存取及最大值得获得;
解题思路
采用动态规划解决本题(如何确定一问题是否属于动态规划问题还不是很清楚)。
以下三点参考解题报告:1185炮兵阵地.ppt(自己实在想不出来了)
逐行向下扫描,考虑到第i行大炮的放置对第i+3行的大炮没有任何影响,这就决定了我们可以用有限的状态数来描述某一行的所有可能情况,因此动态规划成为选择。决定了基本算法,下面选择状态。
分析一个列为10(M的最大值)的表。注意到一个全为P的空列上一共也只有60种合法的Cannon放置方法。具体对一个列数为10的PH表而言,对每一列也只有前两列对其产生影响,因此我们可以用一个二维数组cal [lm] [lm]来记录其上一行处于第x种状态,该行自身出于第y种状态时,从首行扫描到该行时所能存放的最多cannon数。其中lm是列数为M时一列的所有可能合法放置方法,x、y在0到lm-1之间。
Pre[60][60],Now[60][60]
对新行进行扫描时
for(i=0;ilm;i++)
for(j=0;jlm;j++)
for(k=0;klm;k++){
如果当前行,前一行,前二行分别是第i,j,k个状态,并且都能够相容。而now [j] [i]pre [k] [j]+第i个状态新增的cannon数。那么更新now [j] [i]。
}
分析可知,该算法主要通过两个60*60的状态数组实现对现有状态的记录。在循环结束时,now数组中的最大值即为所求。
综上,将本题解题要点以问答形式归结为如下几个问题:
如何根据不同的列数确定有限的状态值lm?
答:可采用如下两种解决办法
A)将最多10种可能的状态(1列至十列,全P)预先存好
B)只存储最多的60种状态,将其他不足60种的按一定规则转化为60种,如,对于一每行6列的,可视其为每行十列,但后4列为H。
2、为何考虑全P分布而不考虑实际存在的PH分布(或曰:如何建立全P 状态值与实际山平原分布状况的对应)?
答:利用全p分布得到一行之中所有可能的炮兵分布状态,之后结合PH分布确定具体某行可能的分布。
3、如何构建状态值与具体炮兵分布状态的对应
答:构建影射函数F(X),将一行的分布状态影射为唯一的数(可利用位运算),而在60*60的数组中,附加一列存贮状态映射数,既将60*60的数组转化为61*61的,附加第0列(行)作为存储空间。
在确定状态值的同时确定个状态即状态影射数。
数据结构与算法
1、Pre与Now的说明与更新方法:
规格:lm*lm;
各点含义:当前遍历至第i行,Pre中存储前i-2,i-1行的各状态下可放入炮数,此时需得到第i行个状态下的最大炮数,即第i-1行,第i行处于各状态下最多可放入炮数。
更新规则:
扫描新行
for(i=0;ilm;i++)
for(j=0;jlm;j++)
for(k=0;klm;k++)
{
if(judge(k,j)judge(j,i)(now [j] [i]pre [k] [j]+num(i)))
now [j] [i]=pre [k] [j]+num(i);
else
文档评论(0)