2023团队天梯模拟赛 L2-3 智能护理中心统计 and L3-1 塔防游戏(23分)
Posted zdxxdz的记录
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2023团队天梯模拟赛 L2-3 智能护理中心统计 and L3-1 塔防游戏(23分)相关的知识,希望对你有一定的参考价值。
L2-3 智能护理中心统计
智能护理中心系统将辖下的护理点分属若干个大区,例如华东区、华北区等;每个大区又分若干个省来进行管理;省又分市,等等。我们将所有这些有管理或护理功能的单位称为“管理结点”。现在已知每位老人由唯一的一个管理结点负责,每个管理结点属于唯一的上级管理结点管辖。你需要实现一个功能,来统计任何一个管理结点所负责照看的老人的数量。
注意这是一个动态问题,即随时可能有老人加入某个管理结点,并且老人是有可能从一个管理结点换到另一个管理结点去的。
输入格式:
输入在第一行中给出 2 个正整数:N(≤104)是老人的总数量,即老人们从 1 到 N 编号;M(≤105)是归属关系的总数。
接下来是 M 行,每行给出一对归属关系,格式为:
A B
表示 A
归属于 B
。A
或 B
如果是某个管理结点,则用不超过 4 个大写英文字母表示其名称;如果是某位老人,则用老人的编号表示。这里每个 A
保证只有唯一的上级归属 B
,且只有这个中心系统本身是没有上级归属的。此外,输入保证没有老人自己承担管理结点的角色,即 B
一定是一个管理结点,不可能是老人的编号。但一个管理结点既可以管辖下级结点,也可以直接护理一部分老人。
随后每行给出一个指令,格式为:
指令 内容
如果 指令
为 T
,则表示有老人要入院或转院,内容
是某老人的编号和要去的管理结点的名称,以空格分隔;如果 指令
为 Q
,则 内容
是一个管理结点的名称,意思是统计这个结点所负责照看的老人的数量;如果 指令
为 E
,则表示输入结束。题目保证指令总数不会超过 100 个。
输出格式:
对每个 T
指令,将对应的老人转存到对应的管理结点名下;对每个 Q
指令,在一行中输出对应管理结点所负责照看的老人的数量。读到 E
指令就结束程序。
输入样例:
10 23
EAST CNTR
ZJ EAST
SD EAST
WEST CNTR
SX WEST
HZ ZJ
JN SD
2 JN
8 JTH
6 XAHP
4 ZDYH
5 ZDYH
ZDYH HZ
HUZ ZJ
JX ZJ
1 JX
3 JN
WZ ZJ
XAHP XIAN
XIAN SX
YL SX
JTH XIAN
7 XAHP
Q EAST
T 1 YL
Q EAST
Q SX
T 8 ZDYH
Q HZ
Q HUZ
T 10 XAHP
Q CNTR
E
输出样例:
5
4
4
3
0
9
题解:老人为叶子节点,考虑到每次只有叶子节点的变化,所以只需要贪心计算叶子节点对对应的这条链的贡献即可
// #include<bits/stdc++.h> using namespace std; #define maxn 610938 #define inf 1290311 int n,m,t; struct no int x,y,nowtime,shu; ; map<pair<int,int> ,pair<int,int>>mp; int mapp[200][200]; queue<no>Q; int dx[6]=1,-1,0,0; int pre1[200]; int pre2[200]; int dy[6]=0,0,1,-1; int mark[200][200]; int tx,ty; int dis[200][200][2]; void bfs() dis[tx][ty][0]=0; dis[tx][ty][1]=0; memset(mark,0,sizeof(mark)); queue<pair<int,int> >K; K.push(make_pair(tx,ty)); while(K.size()) pair<int ,int> p1=K.front(); K.pop(); int x=p1.first; int y=p1.second; mark[x][y]=0; for(int i=0;i<4;i++) if(x+dx[i]>=2&&y+dy[i]>=2&&x+dx[i]<=n+1&&y+dy[i]<=m+1) if(x+dx[i]==tx&&y+dy[i]==ty)continue; if(dis[x+dx[i]][y+dy[i]][0]>dis[x][y][0]+1+mapp[x+dx[i]][y+dy[i]]) dis[x+dx[i]][y+dy[i]][0]=dis[x][y][0]+1+mapp[x+dx[i]][y+dy[i]]; if(!mark[x+dx[i]][y+dy[i]]) mark[x+dx[i]][y+dy[i]]=1; K.push(make_pair(x+dx[i],y+dy[i])); memset(mark,0,sizeof(mark)); K.push(make_pair(tx,ty)); while(K.size()) pair<int ,int> p1=K.front(); K.pop(); int x=p1.first; int y=p1.second; mark[x][y]=0; for(int i=0;i<4;i++) if(x+dx[i]>=2&&y+dy[i]>=2&&x+dx[i]<=n+1&&y+dy[i]<=m+1) if(x+dx[i]==tx&&y+dy[i]==ty)continue; if(dis[x+dx[i]][y+dy[i]][1]>dis[x][y][1]+mapp[x+dx[i]][y+dy[i]]) dis[x+dx[i]][y+dy[i]][1]=dis[x][y][1]+mapp[x+dx[i]][y+dy[i]]; mp[make_pair(x+dx[i],y+dy[i])]=make_pair(x,y); if(!mark[x+dx[i]][y+dy[i]]) mark[x+dx[i]][y+dy[i]]=1; K.push(make_pair(x+dx[i],y+dy[i])); else if(dis[x+dx[i]][y+dy[i]][1]==dis[x][y][1]+mapp[x+dx[i]][y+dy[i]]) if(dis[x+dx[i]][y+dy[i]][0]<=dis[x][y][0]+1+mapp[x+dx[i]][y+dy[i]])continue; mp[make_pair(x+dx[i],y+dy[i])]=make_pair(x,y); if(!mark[x+dx[i]][y+dy[i]]) mark[x+dx[i]][y+dy[i]]=1; K.push(make_pair(x+dx[i],y+dy[i])); int main() cin>>n>>m>>t; for(int i=1;i<=n+2;i++) for(int j=1;j<=m+2;j++) dis[i][j][0]=inf; dis[i][j][1]=inf; cin>>mapp[i][j]; if(i==1||i==n+2||j==1||j==m+2) if(!mapp[i][j]) continue; if(i==1&&(j==1||j==m+2))continue; if(i==n+2&&(j==1||j==m+2))continue; for(int k=0;k<4;k++) if(i+dx[k]>=2&&j+dy[k]>=2&&i+dx[k]<=n+1&&j+dy[k]<=m+1) Q.push(noi+dx[k],j+dy[k],0,mapp[i][j]); if(mapp[i][j]<0) tx=i; ty=j; int fla=0; bfs(); while(Q.size()) no tmp=Q.front(); Q.pop(); int x=tmp.x; int y=tmp.y; int pret=1+mapp[x][y]; int num=tmp.shu; if(num>mapp[x][y]) num-=mapp[x][y]; mapp[x][y]=0; else mapp[x][y]-=num; continue; while(!(x==tx&&y==ty)) pair<int,int>R; R=mp[make_pair(x,y)]; x=R.first; y=R.second; if(mapp[x][y]) if(x==tx&&y==ty)continue; pret=pret+1+mapp[x][y]; if(num>mapp[x][y]) num-=mapp[x][y]; mapp[x][y]=0; else mapp[x][y]-=num; break; else if(x==tx&&y==ty)continue; pret++; if(x==tx&&y==ty) int w=max(0,min(t-pret,num)); mapp[tx][ty]+=w; mapp[tx][ty]=min(mapp[tx][ty],0); if(mapp[tx][ty]==0) fla=1; for(int i=2;i<=n+1;i++) for(int j=2;j<=m+1;j++) if(j==2) cout<<mapp[i][j]; else cout<<" "<<mapp[i][j]; if(j==m+1&&i!=n+1) cout<<endl; if(fla==1) cout<<endl; cout<<"Game Over";
--------------------
L3-1 塔防游戏
有一种简单的塔防游戏是这样的:给定一张由 n 行 m 列个方格子构成的地图,玩家可以任选一个格子放置自己的大本营,还可以在任意一个格子里放置自己的防御堡垒。大本营和每个防御堡垒都有自己的防御能力值 d,表示可以抵御 d 个僵尸的攻击。每一轮游戏开始时,玩家在规定时间内将本级别可以用的防御堡垒布置在地图中,然后僵尸们就从地图边界涌入地图中,向着大本营发起攻击。每轮进攻持续一个固定的时长,结束后剩余的僵尸就原地蒸发。
每队僵尸可以向一个方格的上下左右四个方向移动。如果相邻的目标方格没有堡垒,它们就可以用 1 秒的时间移动过去,否则会被堡垒阻挡或者消灭。对每一队僵尸(从同一地点出发的所有僵尸)而言,每秒会被堡垒消灭 1 个队友,同时消耗掉该堡垒 1 个单位的防御能力。当防御能力降为 0,则该堡垒消失,剩下的僵尸则用 1 秒移动到这个方格继续行进。注意:如果有多支僵尸队都进入了同一个方格,它们并不会合并成一支队伍。
所有的僵尸队都会根据进攻开始时的地图选择被歼灭最少的到达大本营的路线,并且一直按照这个路线行进,中途不因为地图状态的改变而改变。当这样的进攻路径不唯一时,选择能最快到达大本营的路径。题目保证这样的路径所打掉的堡垒的布局是唯一的。
本题就要求你计算出一轮攻击结束时,地图上的布局情况。
输入格式:
输入首先在第一行中给出三个正整数:不超过 100 的 n 和 m,为地图的尺寸;不超过 1000 的 T,为一轮攻击持续的时长。
随后给出 n+2 行,每行给出 m+2 个数字,每行中的数字都用空格分隔,表示攻击开始前地图上的布局。其中第 1 行、第 1 列、第 n+2 行、第 m+2 列是地图边界外僵尸们出发的位置,这些位置上,0
表示没有僵尸,其他正整数表示从该位置出发的僵尸们的数量。而地图中的每个位置上,0
表示没有堡垒,其它正整数表示该位置上堡垒的防御能力值。大本营是一个特殊的建筑,我们用一个负数 −D 表示这里是大本营,其防御能力值为 D。这里的防御值和任一队僵尸的数量都不超过 100。
注意:僵尸不可在地图边界外移动,它们的第一个移动目标必须在地图中,所以四个角落里出现的僵尸可以被忽略,因为它们没有进入地图的途径。
输出格式:
输出 n 行,每行 m 个数字,对应攻击结束后地图上每个方格的状态。状态的表示与输入相同:没有堡垒的地方输出 0
,有堡垒的地方输出其剩余防御值,大本营的位置上输出其剩余防御值的负值。
注意每行数字间以 1 个空格分隔,行首尾不得有多余空格。
当大本营被攻陷时,游戏即刻结束。此时应输出结束时的地图状态,并且在最后一行输出一句 Game Over
。
输入样例 1:
7 5 17
0 0 0 0 13 0 0
0 0 0 0 0 0 0
0 0 0 8 0 0 0
0 0 0 0 2 1 0
0 0 0 7 5 3 0
8 0 1 4 -10 1 0
0 0 0 3 3 0 0
0 0 8 0 9 0 0
0 0 0 4 0 0 0
输出样例 1:
0 0 0 0 0
0 0 8 0 0
0 0 0 2 0
0 0 7 5 0
0 0 0 -1 0
0 0 0 2 0
0 8 0 9 0
样例说明:
地图布局如下图所示。
规模为 13 和 8 的两队僵尸都有两种选择,攻打蓝色或者紫色堡垒都是消耗最少的。在这种情况下,规模为 13 的僵尸队走蓝色比较快,需要 1+1+1+2+4+2=11 秒到达大本营边上;规模为 8 的僵尸队走紫色比较快,需要 1+2+5=8 秒到达大本营边上。
规模为 4 的僵尸队比较惨,只能选择绿色堡垒,最后被大本营边上的绿色堡垒消灭。注意到在攻击过程中,其实它们可以等到紫色堡垒被攻陷之后走紫色原始值为 4 的方格,但是因为路径是在初始状态下选定就不能改的,所以它们不能这样选择。
攻打大本营时,规模为 8 的僵尸队剩下了 3 只先到达,在第 11 秒被大本营消灭。此时大本营还剩 7 个单位的防御值,同时规模为 13 的僵尸队剩下的 8 只进入了大本营相邻的方格,开始攻击。但此时距离本轮结束只剩 6 秒,结果大本营在结束时还剩 1 个单位的防御值,玩家胜。
输入样例 2:
7 5 20
0 0 0 0 13 0 0
0 0 0 0 0 0 0
0 0 0 8 0 0 0
0 0 0 0 2 1 0
0 0 0 7 5 3 0
8 0 1 4 -10 1 0
0 0 0 3 3 0 0
0 0 8 0 9 0 0
0 0 0 4 0 0 0
输出样例 2:
0 0 0 0 0
0 0 8 0 0
0 0 0 2 0
0 0 7 5 0
0 0 0 0 0
0 0 0 2 0
0 8 0 9 0
Game Over
题解:
最开始以为是简单的bfs,然后发现题目中有个很关键的点,所有的僵尸队都会根据进攻开始时的地图选择被歼灭最少的到达大本营的路线,并且一直按照这个路线行进,
中途不因为地图状态的改变而改变。当这样的进攻路径不唯一时,选择能最快到达大本营的路径。题目保证这样的路径所打掉的堡垒的布局是唯一的。
也就是说行经路线是一开始就定好的,所以不用宽搜。所以考虑spfa和dij的做法,由于这俩都是单源最短路,所以考虑反向从大本营开始跑spfa。 dis[i][0]代表破坏堡垒和移动的总消耗的最短路径,
dis[i][1]代表仅破坏堡垒的总消耗的最短路径。然后我们对于每个网格点,记录是哪一个最小损失僵尸的点更新的他就行了。
最后按照这个路径进行模拟就行。
大致思路就是这样,但是天梯赛的数据真的好多坑。。。不想改了。。。
下面附上一个23分的代码
// #include<bits/stdc++.h> using namespace std; #define maxn 610938 #define inf 1290311 int n,m,t; struct no int x,y,nowtime,shu; ; map<pair<int,int> ,pair<int,int>>mp; int mapp[200][200]; queue<no>Q; int dx[6]=1,-1,0,0; int pre1[200]; int pre2[200]; int dy[6]=0,0,1,-1; int mark[200][200]; int tx,ty; int dis[200][200][2]; void bfs() dis[tx][ty][0]=0; dis[tx][ty][1]=0; memset(mark,0,sizeof(mark)); queue<pair<int,int> >K; K.push(make_pair(tx,ty)); while(K.size()) pair<int ,int> p1=K.front(); K.pop(); int x=p1.first; int y=p1.second; mark[x][y]=0; for(int i=0;i<4;i++) if(x+dx[i]>=2&&y+dy[i]>=2&&x+dx[i]<=n+1&&y+dy[i]<=m+1) if(x+dx[i]==tx&&y+dy[i]==ty)continue; if(dis[x+dx[i]][y+dy[i]][0]>dis[x][y][0]+1+mapp[x+dx[i]][y+dy[i]]) dis[x+dx[i]][y+dy[i]][0]=dis[x][y][0]+1+mapp[x+dx[i]][y+dy[i]]; if(!mark[x+dx[i]][y+dy[i]]) mark[x+dx[i]][y+dy[i]]=1; K.push(make_pair(x+dx[i],y+dy[i])); memset(mark,0,sizeof(mark)); K.push(make_pair(tx,ty)); while(K.size()) pair<int ,int> p1=K.front(); K.pop(); int x=p1.first; int y=p1.second; mark[x][y]=0; for(int i=0;i<4;i++) if(x+dx[i]>=2&&y+dy[i]>=2&&x+dx[i]<=n+1&&y+dy[i]<=m+1) if(x+dx[i]==tx&&y+dy[i]==ty)continue; if(dis[x+dx[i]][y+dy[i]][1]>dis[x][y][1]+mapp[x+dx[i]][y+dy[i]]) dis[x+dx[i]][y+dy[i]][1]=dis[x][y][1]+mapp[x+dx[i]][y+dy[i]]; mp[make_pair(x+dx[i],y+dy[i])]=make_pair(x,y); if(!mark[x+dx[i]][y+dy[i]]) mark[x+dx[i]][y+dy[i]]=1; K.push(make_pair(x+dx[i],y+dy[i])); else if(dis[x+dx[i]][y+dy[i]][1]==dis[x][y][1]+mapp[x+dx[i]][y+dy[i]]) if(dis[x+dx[i]][y+dy[i]][0]<=dis[x][y][0]+1+mapp[x+dx[i]][y+dy[i]])continue; mp[make_pair(x+dx[i],y+dy[i])]=make_pair(x,y); if(!mark[x+dx[i]][y+dy[i]]) mark[x+dx[i]][y+dy[i]]=1; K.push(make_pair(x+dx[i],y+dy[i])); int main() cin>>n>>m>>t; for(int i=1;i<=n+2;i++) for(int j=1;j<=m+2;j++) dis[i][j][0]=inf; dis[i][j][1]=inf; cin>>mapp[i][j]; if(i==1||i==n+2||j==1||j==m+2) if(!mapp[i][j]) continue; if(i==1&&(j==1||j==m+2))continue; if(i==n+2&&(j==1||j==m+2))continue; for(int k=0;k<4;k++) if(i+dx[k]>=2&&j+dy[k]>=2&&i+dx[k]<=n+1&&j+dy[k]<=m+1) Q.push(noi+dx[k],j+dy[k],0,mapp[i][j]); if(mapp[i][j]<0) tx=i; ty=j; int fla=0; bfs(); while(Q.size()) no tmp=Q.front(); Q.pop(); int x=tmp.x; int y=tmp.y; int pret=1+mapp[x][y]; int num=tmp.shu; if(num>mapp[x][y]) num-=mapp[x][y]; mapp[x][y]=0; else mapp[x][y]-=num; continue; while(!(x==tx&&y==ty)) pair<int,int>R; R=mp[make_pair(x,y)]; x=R.first; y=R.second; if(mapp[x][y]) if(x==tx&&y==ty)continue; pret=pret+1+mapp[x][y]; if(num>mapp[x][y]) num-=mapp[x][y]; mapp[x][y]=0; else mapp[x][y]-=num; break; else if(x==tx&&y==ty)continue; pret++; if(x==tx&&y==ty) int w=max(0,min(t-pret,num)); mapp[tx][ty]+=w; mapp[tx][ty]=min(mapp[tx][ty],0); if(mapp[tx][ty]==0) fla=1; for(int i=2;i<=n+1;i++) for(int j=2;j<=m+1;j++) if(j==2) cout<<mapp[i][j]; else cout<<" "<<mapp[i][j]; if(j==m+1&&i!=n+1) cout<<endl; if(fla==1) cout<<endl; cout<<"Game Over";
人工智能让老人多了位“照护师”,武昌这些地方已普及…
传感器记录活动信息,
语音控制护理床升降,
离床久了床垫会报警
……
武汉市今年开始,
将全面实施人工智能养老社会实验。
一些人工智能产品已进入
武汉养老机构和老年人家中。
▲ 南湖街爱照护颐养中心照护师通过语音控制智能护理床升降
传感器自动记录上卫生间时长
93岁的向奶奶患有高血压,独自住在武昌区南湖街宝安社区。担心母亲在家里出现意外,向奶奶的女儿联系了南湖街爱照护颐养中心,在家中卫生间水龙头、常坐的桌椅、客厅墙壁、冰箱、房间电视机等物品上,安装了可获取老人每天活动情况数据的无线传感器。
一天下午5时多,颐养中心照护师刘诗文和王小寒上门为向奶奶送晚餐,敲了10多分钟门,却一直没有人开门。意识到老人可能出现意外,两人打开电脑查看向奶奶家中传感器发送的数据。
在颐养中心,通过爱照护系统后台,照护师可查看老人家中传感器实时监测到的用水、坐椅子等的时长数据,时长设定为小于5分钟、5至10分钟和10分钟以上3类。页面上的每种监测数据,分别用不同形状的符号显示,小于5分钟为绿色符号,10分钟以上则为红色符号。“我们不在老人身边时,传感器就像照顾老人的照护师。”刘诗文说。
语音对话可控制护理床升降
“小护小护,我要起床。”在南湖街爱照护颐养中心二楼老人房间,刘诗文对着一张护理床说自己想要起床,护理床立刻发出答复的语音“好的,我们起床吧”。过了两三秒,床的上半部开始慢慢升起。
“小护小护,武汉天气”“小护小护,我要睡觉”“小护小护,我要听黄梅戏”,护理床停止升起后,刘诗文又依次说了上面的3句话,护理床相继完成了播报武汉当天的天气、降下和播放黄梅戏选段的任务。
南湖街爱照护颐养中心共设有29张床位,每个房间都在使用这种智能护理床。刘诗文介绍,每过一段时间,爱照护就会对智能护理床进行升级,最新的护理床将有提醒老人服药、睡眠分析、离床报警等功能。
智能护理床还可以搬进老人家中,颐养中心投入运营以来,周边社区的10多位老人家里都用过这种床,使用完的床颐养中心将进行回收,社区其他老人有需要时,再到老人家中进行安装。
老人晚上离床久了床垫会报警
一些民办养老服务网点也在使用智能床垫。26日下午,武昌区粮道街乐颐轩颐养中心一楼老人房间里,护理员将最新升级的智能床垫铺到了护理床的钢架上。
床垫有近2个鼠标垫那么厚,长80厘米左右,宽约30厘米,床垫铺设的位置大概离床头80厘米远,找准位置铺好后,再铺上老人用的棉絮和床单。
“李万香呼吸心跳异常,请前往处理。”记者在颐养中心监控屏上看到,床垫传来的数据显示李爷爷“心率7,心跳86”,触发床垫对应的守护佳系统的报警,护理员使用的腕表和平板上,也弹出了“李万香呼吸心跳异常,请前往处理”的报警弹窗。
据了解,去年12月,中央网信办发文,确定首批全国人工智能条件下养老社会实验试点城市,武汉、杭州、合肥3个城市入选。
©大成武昌
出品 | 中共武昌区委宣传部 武昌区融媒体中心
来源 | 长江日报
投稿 | dachengwuchang@qq.com
以上是关于2023团队天梯模拟赛 L2-3 智能护理中心统计 and L3-1 塔防游戏(23分)的主要内容,如果未能解决你的问题,请参考以下文章