笔者看到网上算法大多时间复杂度较高,故作此文提出O(N)方法。

2021online普及组【吃豆人】题解

这道题看到,首先想的肯定是一个个找,暴力。

能拿到20分左右的好成绩

但是在画草稿时,把全部路径写出来,就能看到这样一幅图:

然后,就看着,其实有效的路径就只有第一排的那N个点所连接的路径。而且,每个点所连的路径数量<=2条。

而且这些路径都有个特殊性:除了对角线外,第一行每个点向左下or右下延伸的路径最终都会回原位,并且所经过的位置重合。

也就是说,任意一个点它所连接的任意一条路径都会经过第一排。

紧接着想到,在每输入一个a[i][j]这个点时,可以通过一个公式来确定它所连接的一或两条路径开头的列数。(现在我定义:开头都为第一排的点)

于是乎,产生了这么两个函数:

int fleft(x,y) 代表返回第x行y列的点向左延伸(有的不能延伸)所连接的开头列数。

例如这个图上的绿点的返回值为1,即它所连接开头的列数为1列,而在(2,1)的点则为-1,因为它无法向左延伸。

还有一种情况,就是i,j这个位置回到开头需要反弹(拐弯),比如(3,2)这个地方。我们可以看到,它是向上延伸了i-1条线段才到达1行。而它在反弹前走了j-1条线段。

i-1-(j-1)

即一共要走的i-1条线段减去反弹前的j-1条线段就是反弹后走的线段条数。

然后发现,反弹后走的线段条数+1等于开头的列数。还是比如(3,2),它反弹后是走了一条线段,就是1+1=2列。

这是很重要的一个反弹公式:反弹后的开头列数=(i-1)-(j-1)+1

至于怎么判断是反弹还是直接一条线到嘛,就很简单,单独判断i和j的大小关系就行了。我这里采用了保险一点的策略。随你便。

同理,我们可以增加一个int fright(x,y)函数,来返回它所连接的右边的点:

公式已经讲了,fright函数的公式都一个思路。

int fleft(int x,int y)
{if(x==1) return y;if(y==1) return -1;if(y-(x-1)>=1) return y-(x-1);return (x-1)-(y-1)+1;
}
int fright(int x,int y)
{if(x==1) return y;if(y==n) return -1;if(y+(x-1)<=n) return y+(x-1);return n-(x-1-(n-y));
}

f[x]表示第一行第x列的开头的所有豆子数(就是每个开头唯一路径上所有的豆子和)

这样子,我们就可以在输入的时候,把每个点所连接的1~2条路径的开头加到f[]数组

1<=i<=n1<=j<=nscanf(a[i][j]);if(i==1) f[j]+=a[i][j];else{int xx=fleft(i,j),yy=fright(i,j);if(xx!=yy){if(xx!=-1) f[xx]+=a[i][j];if(yy!=-1) f[yy]+=a[i][j];}else f[xx]+=a[i][j];}

所以第一个吃豆人的吃豆数量就为1<=i<=n Max(f[i])

第二个吃豆人的数量也不麻烦,题目说了,吃过的豆不能再吃。

这个题目中的模拟诞生——先确定第一个吃豆人开始吃的行列(就是f[]中最多豆子数的下标),开始模拟路径。每吃到一个豆,向左边延伸的路径和向右边延伸的路径所到达的开头-=a[x][y]

然后写函数体:

void dg(x,y,fx)//行、列、方向
{int l=fleft(x,y),r=fright(x,y);//找到相应开头if(l!=-1) f[l]-=a[x][y];if(r!=-1&&r!=l) f[r]-=a[x][y];//减去豆子a[x][y]=0;//没啥屁用if(c!=0)//由于第一次的起始位置和结束位置相同,所以定义个c标记是否出发{if(x==n||x==1){if(y==1||y==n) return ;//边角if(fx==2) fx=3;else if(fx==1) fx=4;else if(fx==3) fx=2;else if(fx==4) fx=1;}else if(y==n||y==1){if(x==1||x==n) return ;//边角if(fx==2) fx=1;else if(fx==1) fx=2;else if(fx==3) fx=4;else if(fx==4) fx=3;}}x+=bz[fx][0];y+=bz[fx][1];//更改xy坐标if(x==sx&&y==sy&&c==1) return ;else{c=1;dg(x,y,fx);}
}

现在每个开头的豆子数都减去了已经被吃的了,所以——

第二个吃豆人的吃豆数量就为为Max(f[i])1<=i<=n

算上递归和两次取最大,时间复杂度不超过O(4N),算是一个比较快捷的方式。

#include<cstdio>
using namespace std;
int n,a[1005][1005],f[1005],sx=1,sy,sf,c,bz[5][2]={{0,0},{1,-1},{1,1},{-1,1},{-1,-1}},t1=-1,t2=-1;
int fleft(int x,int y)
{if(x==1) return y;if(y==1) return -1;if(y-(x-1)>=1) return y-(x-1);return (x-1)-(y-1)+1;
}
int fright(int x,int y)
{if(x==1) return y;if(y==n) return -1;if(y+(x-1)<=n) return y+(x-1);return n-(x-1-(n-y));
}
void dg(int x,int y,int fx)
{int l=fleft(x,y),r=fright(x,y);if(l!=-1) f[l]-=a[x][y];if(r!=-1&&r!=l) f[r]-=a[x][y];a[x][y]=0;if(c!=0){if(x==n||x==1){if(y==1||y==n) return ;if(fx==2) fx=3;else if(fx==1) fx=4;else if(fx==3) fx=2;else if(fx==4) fx=1;}else if(y==n||y==1){if(x==1||x==n) return ;if(fx==2) fx=1;else if(fx==1) fx=2;else if(fx==3) fx=4;else if(fx==4) fx=3;}}x+=bz[fx][0];y+=bz[fx][1];if(x==sx&&y==sy&&c==1) return ;else{c=1;dg(x,y,fx);}
}
int main()
{scanf("%d",&n);for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){scanf("%d",&a[i][j]);if(i==1) f[j]+=a[i][j];else{int xx=fleft(i,j),yy=fright(i,j);if(xx!=yy){if(xx!=-1) f[xx]+=a[i][j];if(yy!=-1) f[yy]+=a[i][j];}else f[xx]+=a[i][j];}}}for(int i=1;i<=n;i++)if(f[i]>t1){t1=f[i];sy=i;}if(sy==1) sf=2;if(sy==n) sf=1;if(sy>1&&sy<n) sf=1;dg(sx,sy,sf);for(int i=1;i<=n;i++) if(f[i]>t2) t2=f[i];printf("%d",t1+t2);return 0;
}

2021online普及组【吃豆人】O(4N)相关推荐

  1. 摄像头训练的吃豆人,我还是没活几集 | TensorFlow.js

    方栗子 发自 凹非寺  量子位 报道 | 公众号 QbitAI 上个周末,面向JavaScript开发者的TensorFlow.js在TF开发者峰会上发布. 会上,Nikhil Thorat演示的图像 ...

  2. 【历史上的今天】1 月 25 日:电子游戏起源;《吃豆人》作者出生;“蠕虫王”问世

    整理 | 王启隆 透过「历史上的今天」,从过去看未来,从现在亦可以改变未来. 今天是 2022 年 1 月 25 日,在 1979 年的今天,史上发生首例机器人致死事件.美国密歇根州的罗伯特·威廉姆斯 ...

  3. 【历史上的今天】5 月 22 日:Windows 3.0 发布;虚幻引擎诞生;《吃豆人》问世

    整理 | 王启隆 透过「历史上的今天」,从过去看未来,从现在亦可以改变未来. 今天是 2022 年 5 月 22 日,在 1994 年的今天,知名中文论坛曙光 BBS 站开通.1994 年 4 月 2 ...

  4. ​1970年代-大规模集成芯片(LSI)、ASIC和电子游戏吃豆人的诞生

    1970年代发展迅速的十年,BASIC和C高级编程语言在这十年中被广泛采用,大规模集成芯片(LSI).ASIC等也被广泛应用到电子游戏中,同时经典游戏<吃豆人>和<星际迷航>也 ...

  5. 小游戏之欢乐吃豆人canvas重制版

    前言 <Pac-Man>上一次已经写过了,但是用vue写的,整体下来能玩,但是自己感觉不算流畅,而且游戏计算方面也有点欠缺,感兴趣的可看我上一篇文章.这次我又卷土重来,在三四天内用空闲时间 ...

  6. 收藏网页版小游戏:蜘蛛纸牌、扫雷、水果忍者、打地鼠、吃豆人

    学习之余当然是摸鱼了,这里分享几个不用下载直接在线玩耍的游戏.有蜘蛛纸牌网页版在线玩.在线扫雷小游戏.在线玩的水果忍者.吃豆人.打地鼠.3D模仿. 下面我将一个个列出来.欢迎体验收藏! 蜘蛛纸牌:这是 ...

  7. 吃豆人游戏-第12届蓝桥杯Scratch选拔赛真题精选

    [导读]:超平老师计划推出Scratch蓝桥杯真题解析100讲,这是超平老师解读Scratch蓝桥真题系列的第79讲. 蓝桥杯选拔赛每一届都要举行4~5次,和省赛.国赛相比,题目要简单不少,再加上篇幅 ...

  8. c语言吃豆人游戏怎么理解,python 实现简单的吃豆人游戏

    效果展示: 程序简介 1.使用pygame模组 2.在material目录下有一些素材 3.吃豆人的游戏主体 4.吃豆人怪物的AI(未使用深度学习) 主要代码 main.py import pygam ...

  9. Python游戏开发pygame模块,Python实现吃豆人,儿时的回忆

    老规矩,先上效果图 这是一个吃豆人的小游戏.我们8090后这一代人肯定会碰到过.黄点是我们自己,红点就是怪物们.这是最原始版的电子游戏. 然后我们可以在随便一个地方新建一个游戏代码,利用这个包的代码, ...

最新文章

  1. 【Flask】视图高级
  2. SDUT-3362 数据结构实验之图论六:村村通公路
  3. LwIP 之二 网络接口 netif(ethernetif.c、netif.c)
  4. 把 LiveData 用于事件传递那些坑
  5. 2021年1月19日工作日志 - Cypress regression tests build error
  6. Observable观察者模式的使用
  7. rabbitmq接口异常函数方法_分布式系统消息中间件——RabbitMQ的使用进阶篇
  8. 64bit 用户空间内核空间
  9. 负载均衡策略_高负荷小区负载均衡策略建议
  10. windows下桌面便签小工具简单使用技巧
  11. 基于cnn的人脸识别_人脸识别技术:从传统方法到深度学习
  12. 在线旅游中需要上传获取那些信息,对接旅行社护照录入系统
  13. html图片高度撑开,CSS背景图撑开盒子高度
  14. html属于非结构化数据吗,什么是结构化数据非结构化数据和半结构化数据
  15. vim autoformat php,Linux Vim代码格式化/美化插件vim-autoformat安装
  16. python vlookup_Python - 如何使用 Pandas 进行vLookup
  17. 基于数据挖掘的上市公司财务数据分析——第九届“泰迪杯”挑战赛A题优秀作品
  18. 2015湘潭邀请赛 Yada Number
  19. 北京十大推动中国科技发展的人工智能实验室
  20. 微信公众号开发通用任务清单

热门文章

  1. 服务器——SSL/TLS协议信息泄露漏洞(CVE-2016-2183)修复办法
  2. Selenium基础用法
  3. 关于Ransomware备份 哪些是该做和不该做的?
  4. java类求圆的面积周长_java编程 1. 设计一个求圆的面积和周长的类,要求:1计算当半径r,JAVA编程题。编写一个应用程序计算圆的周长和面积,设圆的半...
  5. 经典的大学学习生活心得
  6. scikit-image HOG feature 提取函数使用心得。
  7. 红米4a android9.0,小米-红米4A/5A-通刷-LOS-Beta4.0-安卓9.0.0-来去电归属-农历等-本地化增强适配...
  8. 将OPenCV的Dll 动态连接库改名字,变成自己想要的动态连接库名字
  9. 网易邮箱大师中添加qq邮箱时,需要开启IMAP,一直卡在验证密保的界面
  10. 我的Bug日常:spark基于yarn运行时抛错,内存不足Required executor memory (1024 MB), offHeap memory (0) MB。问题已解决,亲测有用~~~