1897. tank 坦克游戏
显然考虑 $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 坦克游戏的更多相关文章
- bzoj1897. tank 坦克游戏(决策单调性分治)
题目描述 有这样一款新的坦克游戏.在游戏中,你将操纵一辆坦克,在一个N×M的区域中完成一项任务.在此的区域中,将会有许多可攻击的目标,而你每摧毁这样的一个目标,就将获得与目标价值相等的分数.只有获得了 ...
- BZOJ1897 : tank 坦克游戏
设$f[i][j][k]$表示坦克位于$(i,j)$,目前打了不超过$k$个位置的最大得分. 初始值$f[1][1][k]$为在$(1,1)$射程内最大$k$个位置的分数总和. 对于每次移动,会新增一 ...
- 887C. Slava and tanks#轰炸弹坦克游戏(分析)
题目出处:http://codeforces.com/problemset/problem/877/C 题目大意:按照游戏规则,求最小炸弹使用次数 #include<iostream> u ...
- bzoj AC倒序
Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...
- Java 坦克小游戏心得
原本是闲得慌无聊才去尝试做这个项目的,因为小时候玩小霸王的游戏机,那个时候经常玩这个游戏吧,特别是喜欢那种自定义地图的模式,觉得自由度非常不错.总之关于这个游戏,想说的一大堆.鉴于能有个空闲的时间,打 ...
- java学习之坦克大战游戏
总结:由于这几天快过年比较忙然后没怎么写,写代码途中一些经验总结现在给忘记了.这次的小项目感觉比上次写的思路清楚了点.没有之前第一次写那么逻辑混乱,结构也搞的比之前的要好,添加功能比较容易.学习了之前 ...
- Java实现简易联网坦克对战小游戏
目录 介绍 本项目的Github地址 基础版本 游戏的原理, 图形界面(非重点) 游戏逻辑 网络联机 客户端连接上服务器 定义应用层协议 TankNewMsg TankMoveMsg MissileN ...
- 自制Unity小游戏TankHero-2D(2)制作敌方坦克
自制Unity小游戏TankHero-2D(2)制作敌方坦克 我在做这样一个坦克游戏,是仿照(http://game.kid.qq.com/a/20140221/028931.htm)这个游戏制作的. ...
- 自制Unity小游戏TankHero-2D(1)制作主角坦克
自制Unity小游戏TankHero-2D(1)制作主角坦克 我在做这样一个坦克游戏,是仿照(http://game.kid.qq.com/a/20140221/028931.htm)这个游戏制作的. ...
随机推荐
- docker for windows 中挂载文件到容器
docker for windows版本: 宿主机:windows10 场景: 容器是基于microsoft/donet的webapi 想把宿主机的文件挂载到容器中,比方说:a.txt 命令如下: d ...
- Java——package与import
[package] <1>为了解决类的命名冲突问题,Java引入包(package)机制,提供类的多重类命名空间. <2>package作为源文件的第一条语句(缺省时指定为 ...
- CF704D Captain America
http://codeforces.com/problemset/problem/704/D 题解 对于两种颜色的染色,我们可以把它看做选择问题. 比如说红色的代价小,所以我们尽可能多的染红色. 然后 ...
- [BZOJ4205][FJ2015集训]卡牌配对
题目:卡牌配对 传送门:None 题目大意:有$n_1$张$X$类牌和$n_2$张$Y$类类牌,每张卡牌上有三个属性值:$A,B,C$.两张卡牌能够配对,当且仅当,存在至多一项属性值使得两张卡牌该项属 ...
- Python 学习笔记(基础语法 restful 、 Flask 和 Requests)
input 函数 #!/usr/bin/env python3 name = input("\n\n按下 enter 键后退出.") print(name) print() 在 p ...
- 基于自定义的动态数组实现一个栈(Java语言)
关于动态数组,参见我的上一篇关于动态数组的博文https://www.cnblogs.com/inu6/p/11717129.html 1.什么是栈? (1)只能从一端添加元素,也只能从一端取出元素, ...
- mysql分组,行转列
aaarticlea/jpeg;base64,/9j/4QEsRXhpZgAASUkqAAgAAAAPAJqCCgABAAAAwgAAABABAgAQAAAAygAAAAABAwABAAAAQBAAA
- 在bash脚本的for i in编写中将点号``写成单引号‘’或者双引号“”会有什么后果?
编写一个测试脚本: 输入启动命令:https://blog.csdn.net/zhoucheng05_13/article/details/test.sh,结果报错 使用的是root用户,但是仍然提示 ...
- 图论——图的邻接表实现——Java语言(完整demo)
1.图的简单实现方法——邻接矩阵 表示图的一种简单的方法是使用一个一维数组和一个二维数组,称为领接矩阵(adjacent matrix)表示法. 对于每条边(u,v),置A[u,v]等于true:否则 ...
- native-echarts 组件封装
CommunalChart.js /** * 封装 图表组件 */ import React, { Component } from 'react'; import { StyleSheet, Tex ...