第二题:坦克游戏1.0(方法:动态规划)

                                    stO        在此给某位靠打01背包处理射程并AC的大神跪了     Orz


 

   问题描述      

         henry公司最近推出了一款新的坦克游戏。在游戏中,你将操纵一辆坦克,在一个N×M的区域中完成一项任务。在此的区域中,

   将会有许多可攻击的目标,而你每摧毁这样的一个目标,就将获得与目标价值相等的分数。只有获得了最高的分数,任务才算完成。

   同时,为了增加游戏的真实性和难度,该游戏还做了以下的限制:

 

         (1)坦克有射程r的限制。为方便计算,射程r规定为:

                   若坦克位于(x,y)格,则它可攻击的目标(x1,y1)必须满足|x-x1|,|y-y1|∈[0,r]。

         (2)对坦克完成任务的时间有严格限制,规定为t秒。其中,坦克每进行一次移动都需1秒的时间,每攻击一个目标也需1秒的时

         间。时间一到t秒,便对此次任务进行记分。

         (3)坦克最初位于左上角,且移动方向只准是向右或向下,每次只允许移动一格。

         在以上的限制条件下,要完成该任务便成为了一件很难事情。因此,你必须为此编写一个程序,让它助你完成这个艰巨的任务。

 

         数据范围1≤N、M≤50,1≤r≤101≤t≤250。


 

   输入格式(tank.in):

        第一行四个整数N、M、r、t,分别表示区域的长、宽,以及射程和完成任务时间。

        接下来N行是一个N×M的矩阵,对应每个位置上目标的价值。


 

   输出格式(tank.out):

        输出文件仅一个数max,即该任务中可得到的最高分数。


 

   输入样例

       5 5 2 7

       0 5 0 0 4

       0 0 0 0 2

       0 0 0 0 0

       0 0 0 0 0

       5 0 3 0 11


 

   输出样例

        21


 

    分析:

          首先,文中提到的:每次只能向右,向下移动或开炮,所以基本上第一印象就是动规,所以为了完成动规就会想到下面的

    一系列问题:

          

               射程是整道题目的关键,可以说没有了射程问题就是一道普通的动规题目了,直接从1 到 n,1 到 m 循环一遍就有结果

         了,射程是一个(r+1)*(r+1)  的正方形,如果每次打掉价值最高的,那么就可以完成对射程的处理,但于是又引出了下

         面的问题:

               【1】:因为对于一个目标,是只可以打一次的,也就是说这次打过,下次就得换一个了,所以不同时间同一方块能打到

                的最大价值不是固定的,要专门开一个数组来记录并不断更新,这就是代码的难度直线上升。

               【2】:其次,对于一个决策点x,y,记上一秒x,y-1能达到的最大价值为val1,再记上一秒x,y 能达到的最大价值为

                val2,则这一秒在点x,y的价值可以是val1,也可以是 (val2+(此时x,y点能打到最大的价值)), 如果后者大,那么

                这么做的话,势必会选后者添加进该点,但是:设此时x,y能打到的第二大的价值为 t,那么在下一秒,同样决策点是

                x, y,由于val2已经打过最大的,所以这一秒val2只能打掉次大的,所以这时记录的最大价值为val2+最大的价值+加

                次大的价值, 但如果上一秒选的是val1,这一秒它能达到的价值就是val1+最大的价值,那么就会存在一种情况:

                           虽然val1<val2+最大价值,但val1>val2+次大价值,那么就会有val1+最大价值>val2+最大价值+次大价值!

                      也就是说,对于这个决策点x,y,上一秒的决策是最优,但下一秒却不是最优值。这样问题就蛋疼了— —

 

          想到这,就应该要做出选择了:

                【1】:放弃动态规划,选择和搜索探讨一下感情 — — 不要在一棵树上吊死。。

                【2】:霸王硬上弓— — 但就必须对射程进行一个可行的判定。直接全范围搜显然是不行的了— —

          但强搜显然是会超时的Orz(残酷的现实),所以如何对射程进行巧妙的处理必不可少(这不是废话吗— —)


 

    处理射程思路:

           仔细对每一次移动射程变化的观察,会发现:每移动一次,范围内就会多一组数,设决策点为x,y,若x,y由x-1,y 向下移

     动得到:即为从( x+r,y-r 到 y+r)的2r个数。这是一个可喜的发现,因为严格的讲起来,如果对于一个出现在视野内的点,马上

     把他打掉和之后在把它打掉是没有差别的,所以对于这组出现在视野内的数,现在就打掉和之后打掉是没差的,为了方便编程,完

     全可以设定为:要吗就一进视野就马上打掉,要吗就一直都不打。

           所以每次要考虑的数就被固定了,而且相邻两点要考虑的不会有重合(这是非常好的,就免去的上面分析中提到的为了判重而

     不断更新的问题),并且上面分析的前一秒最忧后一秒不一定最优的问题就不存在了。因为做的时候采用一次性添加进要打掉的点

     ,也就是说点是同时添加的(影响不大,没考虑到也没事,只是提到可能会有这种情况)。 

           最后就是要对某个点,打k 个目标的得分进行预处理:

                 记le  [ i , j , k ]为从左边到达( i ,j )这个点,打掉此时k 个新出现在视野中的目标能获得的得分;

                 记up[ i , j , k  ]为从上面到达( i , j)这个点,打掉此时k个新出现在视野中的目标能获得的得分;

      PS:按这个思路,一开始要对已经出现在视野内的点进行预处理~~~


 

    代码:         

 1 var
 2 res:array[-20..251,-100..100,-100..100] of longint;//res是进行动规的数组,
 3                                                    //res[该时间,横坐标,纵坐标]为该时这点得分最大值
 4 val:array[-20..100,-100..100] of longint;          //记录得分点
 5 up,le:array[0..51,0..51,0..100] of longint;        //up,le均为
 6 n,m,r,t:longint;
 7 
 8 Function max(a,b:longint):longint;                 //求两者最大值得函数,返还值为较大者
 9 begin if a>b then exit(a) else exit(b); end;
10 
11 Procedure init;
12 var d:array[0..200] of longint;
13     i,j,l:longint;
14 begin
15   l:=0;
16   readln(n,m,r,t);                     //读入行、列、射程、限时
17   fillchar(res,sizeof(res),$ff);       //初始化动规数组,赋值为-1是为了防止某些不可能情况成立
18   for i:=1   to n   do
19   for j:=1   to m   do read(val[i,j]); //读入目标价值
20   for i:=1   to r+1 do                 //因为按照思路是考虑视野的边界,所以一开始要处理视野内的点
21   for j:=1   to r+1 do
22   if  val[i,j]>0  then begin           //d数组存放该视野中所有的有分的点的分
23    inc(l);
24    d[l]:=val[i,j];
25   end;
26   for i:=1   to l-1 do                 //对这个数组进行排序,因为分高的优先去
27   for j:=i+1 to l   do 
28   if  d[i] < d[j] then begin
29    d[0]:=d[i]; d[i]:=d[j]; d[j]:=d[0];
30   end;
31   for i :=2  to l do inc(d[i],d[i-1]); //做完这步d[x]表示的就是:打掉x 个点的最大得分
32   for i :=1  to l do res[i,1,1]:=d[i]; //初始化站在原地不动一直打的情况
33   close(input);
34 end;
35 
36 Procedure fill;                        //这个过程就是对每个点的新增视野做类似上方的步骤,即预处理
37 var d:array[0..200] of longint; 
38     i,j,k,l,p:longint;                 //l 存的是新增视野内有得分点的数量
39 begin
40   res[0,1,1]:=0;
41   for i:=1 to n do 
42   for j:=1 to m do begin               //枚举每个点  
43     //下面这部分是从上方移动到该点的情况
44     l:=0;                              //清空总数
45     for k:=j-r to j+r do               //查找新增视野中有得分得点
46     if val[i+r,k]>0 then begin         //添加进数组,总数+1
47       inc(l);
48       d[l]:=val[i+r,k];
49     end;
50     for k:=1   to l-1 do               //同样排序
51     for p:=k+1 to l   do
52     if  d[k] < d[p] then begin
53       d[0]:=d[k]; d[k]:=d[p]; d[p]:=d[0];
54     end;
55     for k:=1   to l   do up[i,j,k]:=up[i,j,k-1]+d[k]; //将得到的数据存入up数组中
56     up[i,j,0]:=l;                                     //储存最多可以打多少个
57     //这部分是从左方移动到该点的情况
58     l:=0;                              //清空总数
59     for k:=i-r to i+r do               //查找新增视野中有得分得点
60     if val[k,j+r]>0 then begin         //添加进数组,总数+1
61       inc(l);
62       d[l]:=val[k,j+r];
63     end;
64     for k:=1   to l-1 do               //同样排序
65     for p:=k+1 to l   do
66     if  d[k] < d[p] then begin
67       d[0]:=d[k]; d[k]:=d[p]; d[p]:=d[0];
68     end;
69     for k:=1   to l   do le[i,j,k]:=le[i,j,k-1]+d[k]; //将得到的数据存入up数组中
70     le[i,j,0]:=l;                                     //储存最多可以打多少个
71   end;
72 end;
73 
74 Procedure main;
75 var i,j,z,k:longint;
76 begin
77   for z:=1 to t do                 //把时间做状态
78   for i:=1 to n do                 //枚举每个点
79   for j:=1 to m do
80   if i+j-2<=z then begin           //边界,因为第z 时,走到的点 i,j与1,1的距离不能超过 z
81     res[z,i,j]:=max(res[z-1,i,j],max(res[z-1,i,j-1],res[z-1,i-1,j]));  //直接移动来,不管新增目标
82     for k:=1 to up[i,j,0] do if (z-1-k>0)and(res[z-1-k,i-1,j]>=0) then 
83     res[z,i,j]:=max(res[z,i,j],res[z-1-k,i-1,j]+up[i,j,k]);      //枚举打多少个目标(从上面来这点的)
84     for k:=1 to le[i,j,0] do if (z-1-k>0)and(res[z-1-k,i,j-1]>=0) then 
85     res[z,i,j]:=max(res[z,i,j],res[z-1-k,i,j-1]+le[i,j,k]);      //枚举打多少个目标(从上面左边来的)
86   end else break;
87   k:=0;
88   for i:=1 to n do                 //循环一边寻找最大值
89   for j:=1 to m do
90   if  res[t,i,j]>k then k:=res[t,i,j];
91   writeln(k);                      //输出结果
92 end;
93 
94 begin
95   assign(input,'tank.in');  assign(output,'tank.out');
96   reset(input);             rewrite(output);
97   init;                     fill;
98   main;                     close(output);
99 end.
tank(动规打法)

 

     优化:

           虽然根据测试时给的数据都AC的,但总耗时还是达到了1.4秒多,在完成编程后就可以想想优化:

                      在预处理up和le数组的时候,由于每次新出现在视野内的目标不多,所以一般采用选择排序,但执行次数一多时间就

                上去了— —。所以采用快排的打法并进行一定的修改就可以达到0.30秒AC全数据~,这边贴一个标程:

  1 var  max,n,m,t,r:longint;
  2      map,le:array[0..50,0..50] of longint;
  3      s,temp:array[0..100] of longint;
  4      f:array[0..50,0..50,0..250] of longint;
  5  function min(x,y:longint):longint;
  6   begin
  7    if x<y then min:=x else min:=y;
  8   end;
  9  procedure sort(l,m:longint);
 10   var i,j,mid,t:longint;
 11    begin
 12      i:=l;j:=m;mid:=temp[(l+m) div 2];
 13      repeat
 14       while temp[i]>mid do inc(i);
 15       while temp[j]<mid do dec(j);
 16       if i<=j then begin t:=temp[i];temp[i]:=temp[j];temp[j]:=t;inc(i);dec(j);end;
 17      until i>j;
 18     if i<m then sort(i,m);
 19     if j>l then sort(l,j);
 20    end;
 21  procedure init;
 22   var i,j,k:longint;
 23    begin
 24      assign(input,'tank.in');reset(input);
 25      assign(output,'tank.out');rewrite(output);
 26      readln(n,m,r,t);
 27      for i:=1 to n do
 28       begin
 29        for j:=1 to m do read(map[i,j]);
 30        readln;
 31       end;
 32     k:=0;
 33     fillchar(temp,sizeof(temp),0);
 34     fillchar(le,sizeof(le),0);
 35     max:=0;
 36     for i:=1 to r+1 do
 37      for j:=1 to r+1 do
 38       begin
 39         if map[i,j]<>0 then begin inc(k);
 40         temp[k]:=map[i,j];  end;
 41       end;
 42     sort(1,k);
 43     s[0]:=0;
 44     le[1,1]:=k;
 45     for i:=1 to k do s[i]:=s[i-1]+temp[i];
 46     if k>t then k:=t;
 47     for i:=1 to k do begin f[1,1,i]:=s[i];if f[1,1,i]>max then max:=f[1,1,i];end;
 48    end;
 49  procedure main;
 50   var  i,j,k,p,ir,il,jr,jl,long,ans:longint;
 51    begin
 52      for i:=1 to n-r do
 53       for j:=1 to m-r do
 54        if (i<>1) or (j<>1) then
 55         begin
 56           if i>1 then
 57            begin
 58              if i+r<=n then ir:=i+r else ir:=n;
 59              if j+r<=m then jr:=j+r else jr:=m;
 60              if i-r>=1 then il:=i-r else il:=1;
 61              if j-r>=1 then jl:=j-r else jl:=1;
 62              long:=0;
 63              for k:=1 to jr-jl+1 do if map[ir,k+jl-1]<>0 then
 64               begin inc(long);temp[long]:=map[ir,k+jl-1];end;
 65              sort(1,long);
 66              s[0]:=0;
 67              fillchar(s,sizeof(s),0);
 68              for k:=1 to long do s[k]:=s[k-1]+temp[k];
 69              ans:=min(le[i-1,j]+long,t-(i+j-2));
 70              if ans>le[i,j] then le[i,j]:=ans;
 71              for k:=1 to ans do
 72               begin
 73                 f[i,j,k]:=0;
 74                 for p:=0 to min(long,k) do
 75                  begin
 76                    if f[i-1,j,k-p]+s[p]>f[i,j,k] then
 77                     f[i,j,k]:=f[i-1,j,k-p]+s[p];
 78                  end;
 79                 if f[i,j,k]>max then max:=f[i,j,k];
 80               end;
 81            end;
 82          if j>1 then
 83            begin
 84              if i+r<=n then  ir:=i+r else ir:=n;
 85              if j+r<=m then jr:=j+r else jr:=m;
 86              if i-r>=1 then il:=i-r else il:=1;
 87              if j-r>=1 then jl:=j-r else jl:=1;
 88              long:=0;
 89              for k:=1 to ir-il+1 do if map[k+il-1,jr]<>0 then
 90               begin inc(long);temp[long]:=map[k+il-1,jr];end;
 91              sort(1,long);
 92              s[0]:=0;
 93              fillchar(s,sizeof(s),0);
 94              for k:=1 to long do s[k]:=s[k-1]+temp[k];
 95              ans:=min(le[i,j-1]+long,t-(i+j-2));
 96              if ans>le[i,j] then le[i,j]:=ans;
 97              for k:=1 to ans do
 98               begin
 99                 for p:=0 to min(long,k) do
100                  begin
101                    if f[i,j-1,k-p]+s[p]>f[i,j,k] then
102                     f[i,j,k]:=f[i,j-1,k-p]+s[p];
103                  end;
104                 if f[i,j,k]>max then
105                  begin max:=f[i,j,k];end;
106               end;
107            end;
108         end;
109       writeln(max);
110       close(input);
111       close(output);
112    end;
113  begin
114    init;
115    main;
116  end.
tank(急速优化版)

           PS:该代码无注释,但了解它的思想就看得懂了~


 

     后记:

           一、如文章第一句 — — 用01背包处理新出现在视野中的点也是可以A的— —只比优化慢0.2秒。还可以用贪心— —。

                 反正解决了对视野的处理,将其转化为新视野后就八仙过海,各显神通啦— — 所以不要拘泥于一种算法— —,还是

                 那句话:不要在一棵树上吊死— —

           二、总的来说,无论是对视野的处理还是解决视野问题后的预处理都让我收获了很多,也意识到了自己的很多不足Orz。。


 

                                                                                                                            END。

 

转载于:https://www.cnblogs.com/qq359084415/p/3378274.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/547257.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux 使用systemctl 设置java进程开机启动,管理springboot开机进程

该过程默认已经安装jdk。java程序启动方式有多重&#xff0c;列出如下几种。 1、java -jar demo.jar 使用该命令程序在控制台输出启动&#xff0c;当按下CtrlC和关闭终端时&#xff0c;程序会终止。输出日志&#xff0c;在后面加上 > 文件名&#xff0c;如&#xff1a;java…

Opencv 深度学习识别性别和检测年龄

目录 1基于CNN的性别分类建模原理 1.1 人脸识别 1.2 性别预测 1.3 年龄预测 1.4 结果 2 代码 参考 本教程中&#xff0c;我们将讨论应用于面部的深层学习的有趣应用。我们将估计年龄&#xff0c;并从单个图像中找出该人的性别。模型由GilLevi和TalHassner训练&#xff0…

结构体和联合体

结构体&#xff1a; 8个为一个内存地址 依次向下 联合体&#xff1a; 共用一块内存地址 调试可以gcc -g -o输出编译。然后gdb执行 d打断点。n下一行。p输出。查看每一个所占的内存地址 宏定义和使用 #define 宏名称 “实现什么东西” 大小端 可以自行判断自己电脑 摘自…

Log4j的应用实例

建一张表&#xff0c;如下&#xff1a; create table log4j( logId int not null auto_increment,--流水号 createDate varchar(45) default null,--日志生成时间 thread varchar(45) default null,--当前线程 level varchar(45) default null,--当前日志的级别 …

AgileEAS.NET SOA 中间件平台.Net Socket通信框架-完整应用例子-在线聊天室系统-代码解析...

一、AgileEAS.NET SOA中间件Socket/Tcp框架介绍 在文章AgileEAS.NET SOA 中间件平台.Net Socket通信框架-介绍一文之中我们对AgileEAS.NET SOA中间Socket/Tcp框架进行了总体的介绍&#xff0c;我们知道 AgileEAS.NET SOA中间件Socket/Tcp框架是一套Socket通信的消息中间件&…

小程序如何跳转到各大电商小程序进行CPS赚钱

小程序系统广告门槛高&#xff0c;流量主费用低&#xff0c;个人开发者难以变现。电商CPS也是一种不错的变现方式&#xff0c;在自己的小程序内添加购物优惠导航入口。自己小程序的用户通过导航跳转到电商平台&#xff0c;进行购物&#xff0c;购物完成结算后&#xff0c;作为开…

安装composer以及laravel框架

Linux系统下安装laravel框架 在linux系统下安装laravel&#xff1a; 1.下载到windows系统下&#xff0c;使用FTP(FileZilla是一种快速、可信赖的FTP客户端以及服务器端开放源代码程式&#xff0c;具有多种特色、直接的接口。FileZilla在2002年11月获选为当月最佳推荐专案.)上传…

JVM系列(一)--JVM运行时数据区

随着时间的推移&#xff0c;我觉得有必要将一些之前相对模糊但是对自身技术提高会有帮助的原理、概念、实现进行一下系统的整理&#xff0c;所以就从JVM系列开始吧。本系列主要参考《Java虚拟机规范(第二版)》、周志明先生写的《深入理解Java虚拟机》&#xff0c;具体虚拟机主要…

ceph iscsi安装

ceph iscsi安装 2020-02-24 #安装包 下载包https://github.com/ceph/ceph-iscsi安装ceph-iscsi配置文件安装rbd-target-api所在的ceph-iscsi-cli包 3.1安装依赖python-configshell&#xff0c;网上 3.2安装包里的python-rtslib&#xff08;先卸载老版本&#xff09; 3.3安装…

Tensorflow C3D完成视频动作识别

本文是视频动作识别领域经典的C3D网络的简易实现&#xff0c;可以作为动作识别的入门。论文为<Learning Spatiotemporal Features with 3D Convolutional Networks>(ICCV 2015)。 框架&#xff1a;Tensorflow (1.6)python(2.7)slim 数据集&#xff1a;UCF101. Center f…

去除表中重复的数据

2019独角兽企业重金招聘Python工程师标准>>> 表数据如下&#xff1a; 查询表中重复的数据&#xff1a; SELECT * FROM t_class WHERE classname IN (SELECT classname FROM t_class GROUP BY classname HAVING COUNT(classname) > 1) 结果如下&#xff1a; 显示…

基于动态骨骼的动作识别方法ST-GCN

解读&#xff1a;基于动态骨骼的动作识别方法ST-GCN&#xff08;时空图卷积网络模型&#xff09; 2018年04月09日 01:14:14 我是婉君的 阅读数 16076更多 分类专栏&#xff1a; 计算机视觉 论文 版权声明&#xff1a;本文为博主原创文章&#xff0c;遵循 CC 4.0 BY-SA 版权协…

pyTorch实现C3D模型的视频行为识别实践

1、3D卷积t简介 2、C3D模型原理与PyTorch实现 2.1、C3D模型结构 2.2、C3D视频动作识别&#xff08;附PyTorch代码&#xff09; 2.3、测试结果 参考 1、3D卷积的简介 在图像处理领域&#xff0c;被卷积的都是静态图像&#xff0c;所以使用2D卷积网络就足以。而在视频理解领域&…

HyperLPR Python3车牌识别系统的入门使用

概要 HyperLRP是一个开源的、基于深度学习高性能中文车牌识别库&#xff0c;由北京智云视图科技有限公司开发&#xff0c;支持PHP、C/C、Python语言&#xff0c;Windows/Mac/Linux/Android/IOS 平台。 github地址&#xff1a; https://github.com/zeusees/HyperLPR TODO 支…

java简单自定义Annotation

为什么80%的码农都做不了架构师&#xff1f;>>> 原文内容比较多&#xff0c;这里就简单地说一下。java 5以后增加了3个annotation&#xff0c; Override Deprecated SuppressWarnings 以上annotation用途就不说了。java中自定义annotation需要interface关键字和用到…

Tensorflow Object detection API 在 Windows10 配置

Tensorflow Object detection API 在 Windows10 下的配置不如在 Ubuntu 下配置方便&#xff0c;但还是有方法的&#xff0c;介绍一下我的配置流程。官方目标检测的demo中调用了大量的py文件&#xff0c;不利于项目的部署&#xff0c;因此我将其合并为两个文件 ##1.Tensorflow m…

使用jq的toggle函数实现全选功能遇到的问题

2019独角兽企业重金招聘Python工程师标准>>> 今天做网站后台管理的时候&#xff0c;要实现一个单选全选的功能&#xff0c;很简单的功能&#xff0c;不过&#xff0c;遇到了一个很诡异的问题&#xff0c;写出来跟大家分享下。 功能就不赘述了&#xff0c;大家都懂&…

GO国内镜像加速模块下载

众所周知&#xff0c;国内网络访问国外资源经常会出现不稳定的情况。 Go 生态系统中有着许多中国 Gopher 们无法获取的模块&#xff0c;比如最著名的 golang.org/x/...。并且在中国大陆从 GitHub 获取模块的速度也有点慢。 因此设置 CDN 加速代理就很有必要了&#xff0c;以下…

AbstractEndpoint 和 ProtocolHandler

2019独角兽企业重金招聘Python工程师标准>>> AbstractEndpoint 和 ProtocolHandler /** Licensed to the Apache Software Foundation (ASF) under one or more* contributor license agreements. See the NOTICE file distributed with* this work for additiona…

HOG + SVM 实现图片分类(python3)

前言 大家能看到这篇文章&#xff0c;想必对HOG还是有些了解了&#xff0c;那我就不赘述了&#xff0c;其实我自己不太懂&#xff0c;但是还是比刚开始好一些了。下面我的代码是参考这位博主的&#xff1a;点我查看 上面那位博主是用的cifar-10数据集&#xff0c;但是我们的数…