传送门

显然考虑 $dp$,发现时间只和当前位置和攻击次数有关,设 $F[i][j][k]$ 表示当前位置为 $i,j$ ,攻击了 $k$ 次得到的最大分数

初始 $f[1][1][k]$ 为位置 $1,1$ 能打到的前 $k$ 大位置的分数和

每次移动都会多一行或多一列目标可以选择,攻击时显然优先攻击分数大的位置,因为要排序,

加上原本 $i,j,k$ 复杂度 $O(nm(T+ \log R)R)$ ,考虑优化

先考虑从 $f[i][j-1][k-t]$ 转移到 $f[i][j][k]$,设此时多打的 $t$ 个物品总价值为 $tmp[t]$

那么有 $f[i][j][k]=max(f[i][j-1][k-t]+tmp[t])$,然后我们能(并不)发现转移有单调性,即如果 $i,j,k$ 的最优决策点是 $t$

那么 $i,j,k+1$ 的最优决策点一定不小于 $t$,证明如下:

为了方便理解,我们把 $f[i][j-1][k-t]$ 时选择的数列看成一段区间,把 $tmp$ 看成另一段区间:

假设转移不单调,那么就会出现 $f[i][j][k+1]$ 的最优决策点 $t'<t$,在图上就是这个样子:

上面的是 $f[i][j][k]$ 的最优转移,下面的是 $f[i][j][k+1]$ 的最优转移

因为是最优,那么上面说明,左边的 $p$ 那一段没有右边的 $p$ 那一段的值大(不然就不是最优转移了)

但是下面的却有告诉我们,左边的 $p$ 那一段比右边的 $p+1$ 那一段的值大

然后就矛盾了,所以转移一定的单调的

然后就可以决策单调性分治把复杂度变成 $O(nm(T+R \log R))$

具体看代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
inline int read()
{
int x=,f=; char ch=getchar();
while(ch<''||ch>'') { if(ch=='-') f=-; ch=getchar(); }
while(ch>=''&&ch<='') { x=(x<<)+(x<<)+(ch^); ch=getchar(); }
return x*f;
}
const int N=,M=;
inline bool cmp(const int &x,const int &y) { return x>y; }//从大到小排序
int n,m,S,T,a[N][N],f[N][N][M],ans;
int g[M],v[M],tmp[N*N],tot;
void solve(int ql,int qr,int l,int r)
{
if(ql>qr) return; int mid=ql+qr>>,pos=l;//pos记录决策点
for(int i=l;i<=r&&i<=mid;i++)
{
int t=g[mid-i]+tmp[i];
if(t>v[mid]) v[mid]=t,pos=i;
}
solve(ql,mid-,l,pos); solve(mid+,qr,pos,r);
}
int main()
{
memset(f,~0x3f,sizeof(f));//一开始都不合法
n=read(),m=read(),S=read(),T=read();
for(int i=;i<=n;i++)
for(int j=;j<=m;j++) a[i][j]=read();
for(int i=;i<=S+;i++)
for(int j=;j<=S+;j++) if(a[i][j]>) tmp[++tot]=a[i][j];
sort(tmp+,tmp+tot+,cmp); tot=min(tot,T);
f[][][]=; for(int k=;k<=tot;k++) f[][][k]=f[][][k-]+tmp[k];//初始化
int nn=max(,n-S),mm=max(,m-S);
for(int i=;i<=nn;i++)
for(int j=;j<=mm;j++)
{
int mx=T-i-j+; if(mx<=) continue;//mx是剩下的时间
if(i>)
{
for(int k=;k<=mx;k++) g[k]=v[k]=f[i-][j][k];
if(i+S<=n)
{
tot=;
for(int k=max(,j-S);k<=min(j+S,m);k++) if(a[i+S][k]>) tmp[++tot]=a[i+S][k];
sort(tmp+,tmp+tot+,cmp); for(int k=;k<=tot;k++) tmp[k]+=tmp[k-];
if(tot) solve(,mx,,tot);
}
for(int k=;k<=mx;k++) f[i][j][k]=v[k];
}
if(j>)
{
for(int k=;k<=mx;k++) g[k]=v[k]=f[i][j-][k];
if(j+S<=m)
{
tot=;
for(int k=max(,i-S);k<=min(i+S,n);k++) if(a[k][j+S]>) tmp[++tot]=a[k][j+S];
sort(tmp+,tmp+tot+,cmp); for(int k=;k<=tot;k++) tmp[k]+=tmp[k-];
if(tot) solve(,mx,,tot);
}
for(int k=;k<=mx;k++) f[i][j][k]=max(f[i][j][k],v[k]);
}
for(int k=;k<=mx;k++) ans=max(ans,f[i][j][k]);
}
printf("%d\n",ans);
return ;
}

1897. tank 坦克游戏的更多相关文章

  1. bzoj1897. tank 坦克游戏(决策单调性分治)

    题目描述 有这样一款新的坦克游戏.在游戏中,你将操纵一辆坦克,在一个N×M的区域中完成一项任务.在此的区域中,将会有许多可攻击的目标,而你每摧毁这样的一个目标,就将获得与目标价值相等的分数.只有获得了 ...

  2. BZOJ1897 : tank 坦克游戏

    设$f[i][j][k]$表示坦克位于$(i,j)$,目前打了不超过$k$个位置的最大得分. 初始值$f[1][1][k]$为在$(1,1)$射程内最大$k$个位置的分数总和. 对于每次移动,会新增一 ...

  3. 887C. Slava and tanks#轰炸弹坦克游戏(分析)

    题目出处:http://codeforces.com/problemset/problem/877/C 题目大意:按照游戏规则,求最小炸弹使用次数 #include<iostream> u ...

  4. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

  5. Java 坦克小游戏心得

    原本是闲得慌无聊才去尝试做这个项目的,因为小时候玩小霸王的游戏机,那个时候经常玩这个游戏吧,特别是喜欢那种自定义地图的模式,觉得自由度非常不错.总之关于这个游戏,想说的一大堆.鉴于能有个空闲的时间,打 ...

  6. java学习之坦克大战游戏

    总结:由于这几天快过年比较忙然后没怎么写,写代码途中一些经验总结现在给忘记了.这次的小项目感觉比上次写的思路清楚了点.没有之前第一次写那么逻辑混乱,结构也搞的比之前的要好,添加功能比较容易.学习了之前 ...

  7. Java实现简易联网坦克对战小游戏

    目录 介绍 本项目的Github地址 基础版本 游戏的原理, 图形界面(非重点) 游戏逻辑 网络联机 客户端连接上服务器 定义应用层协议 TankNewMsg TankMoveMsg MissileN ...

  8. 自制Unity小游戏TankHero-2D(2)制作敌方坦克

    自制Unity小游戏TankHero-2D(2)制作敌方坦克 我在做这样一个坦克游戏,是仿照(http://game.kid.qq.com/a/20140221/028931.htm)这个游戏制作的. ...

  9. 自制Unity小游戏TankHero-2D(1)制作主角坦克

    自制Unity小游戏TankHero-2D(1)制作主角坦克 我在做这样一个坦克游戏,是仿照(http://game.kid.qq.com/a/20140221/028931.htm)这个游戏制作的. ...

随机推荐

  1. git的初步研究1

    工作中很多项目再往git上迁移,所以打算研究下git git是个版本控制系统 理解git工作区.暂存区.版本库的概念 工作区:在电脑中能看到的目录 暂存区:index即索引 即首先add加入暂存区 c ...

  2. Manacher模板( 线性求最长回文子串 )

    模板 #include<stdio.h> #include<string.h> #include<algorithm> #include<map> us ...

  3. [CF1177B]Digits Sequence (Hard Edition)题解

    一个简单的模拟,首先先计算当前是几位数,然后根据几位数推断当前的数是什么,然后求出该位即可 #include <cstdio> int main(){ long long k; scanf ...

  4. 【Java】SpringBoot整合RabbitMQ

    介绍 RabbitMQ 即一个消息队列,主要是用来实现应用程序的异步和解耦,同时也能起到消息缓冲,消息分发的作用. RabbitMQ是实现AMQP(高级消息队列协议)的消息中间件的一种,AMQP,即A ...

  5. 回声状态网络ESN(Echo State Networks)

    1.1 网络结构 ESN通过随机地部署大规模系数链接的神经元构成网络隐层,一般称为"储备池".ESN网络具有的特点如下: (1)包含数目相对较多的神经元: (2)神经元之间的连接关 ...

  6. shell中的=~的简单用法

    其中 ~ 其实是对后面的正则表达式表示匹配的意思,如果匹配就输出1, 不匹配就输出0 [[ $test =~ ^[0-9]+ ]] && echo 1 || echo 0

  7. mysql中的collate关键字是什么意思?

    CREATE TABLE `tb_order` ( `order_id` varchar(50) COLLATE utf8_bin DEFAULT NULL COMMENT '订单id', `paym ...

  8. C++中的集合和字典

    https://blog.csdn.net/sinat_39037640/article/details/74080509

  9. HDFS——完全分布式搭建

    架构 NN--namenode SNN--secondnamenode DN--datanode hadoop_env.sh中修改JAVA_HOME core-site.xml <propert ...

  10. ES与CQRS之旅

    引言 领域驱动设计(Domain Driven Design),使用统一的建模语言.专注业务领域分析.采取化整为零并反复迭代的方式,以业务领域模型为圆心,向外辐射到系统轮廓的勾勒.具体模块的实现,为我 ...